Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / client / gl_helper.cc
index c90d5b5..0ba9193 100644 (file)
 #include "base/message_loop/message_loop.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
+#include "content/common/gpu/client/gl_helper_readback_support.h"
 #include "content/common/gpu/client/gl_helper_scaling.h"
+#include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/common/mailbox.h"
+#include "gpu/command_buffer/common/mailbox_holder.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_util.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
 #include "third_party/skia/include/core/SkRegion.h"
 #include "ui/gfx/rect.h"
 #include "ui/gfx/size.h"
-#include "ui/gl/gl_bindings.h"
 
-using WebKit::WebGLId;
-using WebKit::WebGraphicsContext3D;
+using gpu::gles2::GLES2Interface;
 
 namespace {
 
+class ScopedFlush {
+ public:
+  explicit ScopedFlush(gpu::gles2::GLES2Interface* gl) : gl_(gl) {}
+
+  ~ScopedFlush() { gl_->Flush(); }
+
+ private:
+  gpu::gles2::GLES2Interface* gl_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedFlush);
+};
+
 // Helper class for allocating and holding an RGBA texture of a given
 // size and an associated framebuffer.
 class TextureFrameBufferPair {
  public:
-  TextureFrameBufferPair(WebGraphicsContext3D* context,
-                         gfx::Size size)
-      : texture_(context, context->createTexture()),
-        framebuffer_(context, context->createFramebuffer()),
-        size_(size) {
-    content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context,
-                                                               texture_);
-    context->texImage2D(GL_TEXTURE_2D,
-                        0,
-                        GL_RGBA,
-                        size.width(),
-                        size.height(),
-                        0,
-                        GL_RGBA,
-                        GL_UNSIGNED_BYTE,
-                        NULL);
+  TextureFrameBufferPair(GLES2Interface* gl, gfx::Size size)
+      : texture_(gl), framebuffer_(gl), size_(size) {
+    content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl, texture_);
+    gl->TexImage2D(GL_TEXTURE_2D,
+                   0,
+                   GL_RGBA,
+                   size.width(),
+                   size.height(),
+                   0,
+                   GL_RGBA,
+                   GL_UNSIGNED_BYTE,
+                   NULL);
     content::ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
-        context,
-        framebuffer_);
-    context->framebufferTexture2D(GL_FRAMEBUFFER,
-                                  GL_COLOR_ATTACHMENT0,
-                                  GL_TEXTURE_2D,
-                                  texture_,
-                                  0);
+        gl, framebuffer_);
+    gl->FramebufferTexture2D(
+        GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_, 0);
   }
 
-  WebGLId texture() const { return texture_.id(); }
-  WebGLId framebuffer() const { return framebuffer_.id(); }
+  GLuint texture() const { return texture_.id(); }
+  GLuint framebuffer() const { return framebuffer_.id(); }
   gfx::Size size() const { return size_; }
 
  private:
@@ -78,21 +82,18 @@ class TextureFrameBufferPair {
 // when the output of a scaler is to be sent to a readback.
 class ScalerHolder {
  public:
-  ScalerHolder(WebGraphicsContext3D* context,
-               content::GLHelper::ScalerInterface *scaler)
-      : texture_and_framebuffer_(context, scaler->DstSize()),
-        scaler_(scaler) {
-  }
+  ScalerHolder(GLES2Interface* gl, content::GLHelper::ScalerInterface* scaler)
+      : texture_and_framebuffer_(gl, scaler->DstSize()), scaler_(scaler) {}
 
-  void Scale(WebKit::WebGLId src_texture) {
+  void Scale(GLuint src_texture) {
     scaler_->Scale(src_texture, texture_and_framebuffer_.texture());
   }
 
   content::GLHelper::ScalerInterface* scaler() const { return scaler_.get(); }
-  TextureFrameBufferPair *texture_and_framebuffer() {
+  TextureFrameBufferPairtexture_and_framebuffer() {
     return &texture_and_framebuffer_;
   }
-  WebGLId texture() const { return texture_and_framebuffer_.texture(); }
+  GLuint texture() const { return texture_and_framebuffer_.texture(); }
 
  private:
   TextureFrameBufferPair texture_and_framebuffer_;
@@ -104,69 +105,82 @@ class ScalerHolder {
 }  // namespace
 
 namespace content {
+typedef GLHelperReadbackSupport::FormatSupport FormatSupport;
 
 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates
 // the data needed for it.
-class GLHelper::CopyTextureToImpl :
-      public base::SupportsWeakPtr<GLHelper::CopyTextureToImpl> {
+class GLHelper::CopyTextureToImpl
+    : public base::SupportsWeakPtr<GLHelper::CopyTextureToImpl> {
  public:
-  CopyTextureToImpl(WebGraphicsContext3D* context,
+  CopyTextureToImpl(GLES2Interface* gl,
                     gpu::ContextSupport* context_support,
                     GLHelper* helper)
-      : context_(context),
+      : gl_(gl),
         context_support_(context_support),
         helper_(helper),
-        flush_(context),
+        flush_(gl),
         max_draw_buffers_(0) {
-    std::string extensions_string = " " +
-        UTF16ToASCII(context_->getString(GL_EXTENSIONS)) + " ";
+    const GLubyte* extensions = gl_->GetString(GL_EXTENSIONS);
+    if (!extensions)
+      return;
+    std::string extensions_string =
+        " " + std::string(reinterpret_cast<const char*>(extensions)) + " ";
     if (extensions_string.find(" GL_EXT_draw_buffers ") != std::string::npos) {
-      context_->getIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers_);
+      gl_->GetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &max_draw_buffers_);
     }
   }
-  ~CopyTextureToImpl() {
-    CancelRequests();
-  }
+  ~CopyTextureToImpl() { CancelRequests(); }
 
-  WebGLId ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
-                                  uint32 sync_point) {
+  GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
+                                 uint32 sync_point) {
     return helper_->ConsumeMailboxToTexture(mailbox, sync_point);
   }
 
   void CropScaleReadbackAndCleanTexture(
-      WebGLId src_texture,
+      GLuint src_texture,
       const gfx::Size& src_size,
       const gfx::Rect& src_subrect,
       const gfx::Size& dst_size,
       unsigned char* out,
+      const SkColorType out_color_type,
       const base::Callback<void(bool)>& callback,
       GLHelper::ScalerQuality quality);
 
-  void ReadbackTextureSync(WebGLId texture,
+  void ReadbackTextureSync(GLuint texture,
                            const gfx::Rect& src_rect,
-                           unsigned char* out);
+                           unsigned char* out,
+                           SkColorType format);
+
+  void ReadbackTextureAsync(GLuint texture,
+                            const gfx::Size& dst_size,
+                            unsigned char* out,
+                            SkColorType color_type,
+                            const base::Callback<void(bool)>& callback);
 
   // Reads back bytes from the currently bound frame buffer.
   // Note that dst_size is specified in bytes, not pixels.
-  void ReadbackAsync(
-      const gfx::Size& dst_size,
-      int32 bytes_per_row,     // generally dst_size.width() * 4
-      int32 row_stride_bytes,  // generally dst_size.width() * 4
-      unsigned char* out,
-      const base::Callback<void(bool)>& callback);
+  void ReadbackAsync(const gfx::Size& dst_size,
+                     int32 bytes_per_row,     // generally dst_size.width() * 4
+                     int32 row_stride_bytes,  // generally dst_size.width() * 4
+                     unsigned char* out,
+                     GLenum format,
+                     GLenum type,
+                     size_t bytes_per_pixel,
+                     const base::Callback<void(bool)>& callback);
 
   void ReadbackPlane(TextureFrameBufferPair* source,
                      const scoped_refptr<media::VideoFrame>& target,
                      int plane,
                      int size_shift,
                      const gfx::Rect& dst_subrect,
+                     ReadbackSwizzle swizzle,
                      const base::Callback<void(bool)>& callback);
 
-  WebKit::WebGLId CopyAndScaleTexture(WebGLId texture,
-                                      const gfx::Size& src_size,
-                                      const gfx::Size& dst_size,
-                                      bool vertically_flip_texture,
-                                      GLHelper::ScalerQuality quality);
+  GLuint CopyAndScaleTexture(GLuint texture,
+                             const gfx::Size& src_size,
+                             const gfx::Size& dst_size,
+                             bool vertically_flip_texture,
+                             GLHelper::ScalerQuality quality);
 
   ReadbackYUVInterface* CreateReadbackPipelineYUV(
       GLHelper::ScalerQuality quality,
@@ -179,9 +193,13 @@ class GLHelper::CopyTextureToImpl :
 
   // Returns the maximum number of draw buffers available,
   // 0 if GL_EXT_draw_buffers is not available.
-  WebKit::WGC3Dint MaxDrawBuffers() const {
-    return max_draw_buffers_;
-  }
+  GLint MaxDrawBuffers() const { return max_draw_buffers_; }
+
+  FormatSupport GetReadbackConfig(SkColorType color_type,
+                                  bool can_swizzle,
+                                  GLenum* format,
+                                  GLenum* type,
+                                  size_t* bytes_per_pixel);
 
  private:
   // A single request to CropScaleReadbackAndCleanTexture.
@@ -190,7 +208,7 @@ class GLHelper::CopyTextureToImpl :
   // thread marks that it handles the request by resetting the pixels field
   // (meaning it guarantees that the callback with be called).
   // In either case, the callback must be called exactly once, and the texture
-  // must be deleted by the main thread context.
+  // must be deleted by the main thread gl.
   struct Request {
     Request(const gfx::Size& size_,
             int32 bytes_per_row_,
@@ -204,8 +222,7 @@ class GLHelper::CopyTextureToImpl :
           pixels(pixels_),
           callback(callback_),
           buffer(0),
-          query(0) {
-    }
+          query(0) {}
 
     bool done;
     gfx::Size size;
@@ -214,14 +231,14 @@ class GLHelper::CopyTextureToImpl :
     unsigned char* pixels;
     base::Callback<void(bool)> callback;
     GLuint buffer;
-    WebKit::WebGLId query;
+    GLuint query;
   };
 
   // A readback pipeline that also converts the data to YUV before
   // reading it back.
   class ReadbackYUVImpl : public ReadbackYUVInterface {
    public:
-    ReadbackYUVImpl(WebGraphicsContext3D* context,
+    ReadbackYUVImpl(GLES2Interface* gl,
                     CopyTextureToImpl* copy_impl,
                     GLHelperScaling* scaler_impl,
                     GLHelper::ScalerQuality quality,
@@ -229,23 +246,22 @@ class GLHelper::CopyTextureToImpl :
                     const gfx::Rect& src_subrect,
                     const gfx::Size& dst_size,
                     const gfx::Rect& dst_subrect,
-                    bool flip_vertically);
+                    bool flip_vertically,
+                    ReadbackSwizzle swizzle);
 
-    virtual void ReadbackYUV(
-        const gpu::Mailbox& mailbox,
-        uint32 sync_point,
-        const scoped_refptr<media::VideoFrame>& target,
-        const base::Callback<void(bool)>& callback) OVERRIDE;
+    void ReadbackYUV(const gpu::Mailbox& mailbox,
+                     uint32 sync_point,
+                     const scoped_refptr<media::VideoFrame>& target,
+                     const base::Callback<void(bool)>& callback) override;
 
-    virtual ScalerInterface* scaler() OVERRIDE {
-      return scaler_.scaler();
-    }
+    ScalerInterface* scaler() override { return scaler_.scaler(); }
 
    private:
-    WebGraphicsContext3D* context_;
+    GLES2Interface* gl_;
     CopyTextureToImpl* copy_impl_;
     gfx::Size dst_size_;
     gfx::Rect dst_subrect_;
+    ReadbackSwizzle swizzle_;
     ScalerHolder scaler_;
     ScalerHolder y_;
     ScalerHolder u_;
@@ -259,7 +275,7 @@ class GLHelper::CopyTextureToImpl :
   // may not be supported on all platforms.
   class ReadbackYUV_MRT : public ReadbackYUVInterface {
    public:
-    ReadbackYUV_MRT(WebGraphicsContext3D* context,
+    ReadbackYUV_MRT(GLES2Interface* gl,
                     CopyTextureToImpl* copy_impl,
                     GLHelperScaling* scaler_impl,
                     GLHelper::ScalerQuality quality,
@@ -267,24 +283,23 @@ class GLHelper::CopyTextureToImpl :
                     const gfx::Rect& src_subrect,
                     const gfx::Size& dst_size,
                     const gfx::Rect& dst_subrect,
-                    bool flip_vertically);
+                    bool flip_vertically,
+                    ReadbackSwizzle swizzle);
 
-    virtual void ReadbackYUV(
-        const gpu::Mailbox& mailbox,
-        uint32 sync_point,
-        const scoped_refptr<media::VideoFrame>& target,
-        const base::Callback<void(bool)>& callback) OVERRIDE;
+    void ReadbackYUV(const gpu::Mailbox& mailbox,
+                     uint32 sync_point,
+                     const scoped_refptr<media::VideoFrame>& target,
+                     const base::Callback<void(bool)>& callback) override;
 
-    virtual ScalerInterface* scaler() OVERRIDE {
-      return scaler_.scaler();
-    }
+    ScalerInterface* scaler() override { return scaler_.scaler(); }
 
    private:
-    WebGraphicsContext3D* context_;
+    GLES2Interface* gl_;
     CopyTextureToImpl* copy_impl_;
     gfx::Size dst_size_;
     gfx::Rect dst_subrect_;
     GLHelper::ScalerQuality quality_;
+    ReadbackSwizzle swizzle_;
     ScalerHolder scaler_;
     scoped_ptr<content::GLHelperScaling::ShaderInterface> pass1_shader_;
     scoped_ptr<content::GLHelperScaling::ShaderInterface> pass2_shader_;
@@ -299,24 +314,45 @@ class GLHelper::CopyTextureToImpl :
   // Copies the block of pixels specified with |src_subrect| from |src_texture|,
   // scales it to |dst_size|, writes it into a texture, and returns its ID.
   // |src_size| is the size of |src_texture|.
-  WebGLId ScaleTexture(WebGLId src_texture,
-                       const gfx::Size& src_size,
-                       const gfx::Rect& src_subrect,
-                       const gfx::Size& dst_size,
-                       bool vertically_flip_texture,
-                       bool swizzle,
-                       GLHelper::ScalerQuality quality);
+  GLuint ScaleTexture(GLuint src_texture,
+                      const gfx::Size& src_size,
+                      const gfx::Rect& src_subrect,
+                      const gfx::Size& dst_size,
+                      bool vertically_flip_texture,
+                      bool swizzle,
+                      SkColorType color_type,
+                      GLHelper::ScalerQuality quality);
+
+  // Converts each four consecutive pixels of the source texture into one pixel
+  // in the result texture with each pixel channel representing the grayscale
+  // color of one of the four original pixels:
+  // R1G1B1A1 R2G2B2A2 R3G3B3A3 R4G4B4A4 -> X1X2X3X4
+  // The resulting texture is still an RGBA texture (which is ~4 times narrower
+  // than the original). If rendered directly, it wouldn't show anything useful,
+  // but the data in it can be used to construct a grayscale image.
+  // |encoded_texture_size| is the exact size of the resulting RGBA texture. It
+  // is equal to src_size.width()/4 rounded upwards. Some channels in the last
+  // pixel ((-src_size.width()) % 4) to be exact) are padding and don't contain
+  // useful data.
+  // If swizzle is set to true, the transformed pixels are reordered:
+  // R1G1B1A1 R2G2B2A2 R3G3B3A3 R4G4B4A4 -> X3X2X1X4.
+  GLuint EncodeTextureAsGrayscale(GLuint src_texture,
+                                  const gfx::Size& src_size,
+                                  gfx::Size* const encoded_texture_size,
+                                  bool vertically_flip_texture,
+                                  bool swizzle);
 
   static void nullcallback(bool success) {}
-  void ReadbackDone(Request *request);
+  void ReadbackDone(Request *request, int bytes_per_pixel);
   void FinishRequest(Request* request, bool result);
   void CancelRequests();
 
   static const float kRGBtoYColorWeights[];
   static const float kRGBtoUColorWeights[];
   static const float kRGBtoVColorWeights[];
+  static const float kRGBtoGrayscaleColorWeights[];
 
-  WebGraphicsContext3D* context_;
+  GLES2Interface* gl_;
   gpu::ContextSupport* context_support_;
   GLHelper* helper_;
 
@@ -325,16 +361,15 @@ class GLHelper::CopyTextureToImpl :
   ScopedFlush flush_;
 
   std::queue<Request*> request_queue_;
-  WebKit::WGC3Dint max_draw_buffers_;
+  GLint max_draw_buffers_;
 };
 
-GLHelper::ScalerInterface* GLHelper::CreateScaler(
-    ScalerQuality quality,
-    const gfx::Size& src_size,
-    const gfx::Rect& src_subrect,
-    const gfx::Size& dst_size,
-    bool vertically_flip_texture,
-    bool swizzle) {
+GLHelper::ScalerInterface* GLHelper::CreateScaler(ScalerQuality quality,
+                                                  const gfx::Size& src_size,
+                                                  const gfx::Rect& src_subrect,
+                                                  const gfx::Size& dst_size,
+                                                  bool vertically_flip_texture,
+                                                  bool swizzle) {
   InitScalerImpl();
   return scaler_impl_->CreateScaler(quality,
                                     src_size,
@@ -344,14 +379,38 @@ GLHelper::ScalerInterface* GLHelper::CreateScaler(
                                     swizzle);
 }
 
-WebGLId GLHelper::CopyTextureToImpl::ScaleTexture(
-    WebGLId src_texture,
+GLuint GLHelper::CopyTextureToImpl::ScaleTexture(
+    GLuint src_texture,
     const gfx::Size& src_size,
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     bool vertically_flip_texture,
     bool swizzle,
+    SkColorType color_type,
     GLHelper::ScalerQuality quality) {
+  GLuint dst_texture = 0u;
+  gl_->GenTextures(1, &dst_texture);
+  {
+    GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
+    ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
+
+    // Use GL_RGBA for destination/temporary texture unless we're working with
+    // 16-bit data
+    if (color_type == kRGB_565_SkColorType) {
+      format = GL_RGB;
+      type = GL_UNSIGNED_SHORT_5_6_5;
+    }
+
+    gl_->TexImage2D(GL_TEXTURE_2D,
+                    0,
+                    format,
+                    dst_size.width(),
+                    dst_size.height(),
+                    0,
+                    format,
+                    type,
+                    NULL);
+  }
   scoped_ptr<ScalerInterface> scaler(
       helper_->CreateScaler(quality,
                             src_size,
@@ -359,21 +418,44 @@ WebGLId GLHelper::CopyTextureToImpl::ScaleTexture(
                             dst_size,
                             vertically_flip_texture,
                             swizzle));
+  scaler->Scale(src_texture, dst_texture);
+  return dst_texture;
+}
 
-  WebGLId dst_texture = context_->createTexture();
+GLuint GLHelper::CopyTextureToImpl::EncodeTextureAsGrayscale(
+    GLuint src_texture,
+    const gfx::Size& src_size,
+    gfx::Size* const encoded_texture_size,
+    bool vertically_flip_texture,
+    bool swizzle) {
+  GLuint dst_texture = 0u;
+  gl_->GenTextures(1, &dst_texture);
+  // The size of the encoded texture.
+  *encoded_texture_size =
+      gfx::Size((src_size.width() + 3) / 4, src_size.height());
   {
-    ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, dst_texture);
-    context_->texImage2D(GL_TEXTURE_2D,
-                         0,
-                         GL_RGBA,
-                         dst_size.width(),
-                         dst_size.height(),
-                         0,
-                         GL_RGBA,
-                         GL_UNSIGNED_BYTE,
-                         NULL);
+    ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
+    gl_->TexImage2D(GL_TEXTURE_2D,
+                    0,
+                    GL_RGBA,
+                    encoded_texture_size->width(),
+                    encoded_texture_size->height(),
+                    0,
+                    GL_RGBA,
+                    GL_UNSIGNED_BYTE,
+                    NULL);
   }
-  scaler->Scale(src_texture, dst_texture);
+
+  helper_->InitScalerImpl();
+  scoped_ptr<ScalerInterface> grayscale_scaler(
+      helper_->scaler_impl_.get()->CreatePlanarScaler(
+          src_size,
+          gfx::Rect(0, 0, (src_size.width() + 3) & ~3, src_size.height()),
+          *encoded_texture_size,
+          vertically_flip_texture,
+          swizzle,
+          kRGBtoGrayscaleColorWeights));
+  grayscale_scaler->Scale(src_texture, dst_texture);
   return dst_texture;
 }
 
@@ -382,94 +464,209 @@ void GLHelper::CopyTextureToImpl::ReadbackAsync(
     int32 bytes_per_row,
     int32 row_stride_bytes,
     unsigned char* out,
+    GLenum format,
+    GLenum type,
+    size_t bytes_per_pixel,
     const base::Callback<void(bool)>& callback) {
-  Request* request = new Request(dst_size,
-                                 bytes_per_row,
-                                 row_stride_bytes,
-                                 out,
-                                 callback);
+  TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::ReadbackAsync");
+  Request* request =
+      new Request(dst_size, bytes_per_row, row_stride_bytes, out, callback);
   request_queue_.push(request);
-  request->buffer = context_->createBuffer();
-  context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
-                       request->buffer);
-  context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
-                       4 * dst_size.GetArea(),
-                       NULL,
-                       GL_STREAM_READ);
-
-  request->query = context_->createQueryEXT();
-  context_->beginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM,
-                          request->query);
-  context_->readPixels(0, 0, dst_size.width(), dst_size.height(),
-                       GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-  context_->endQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM);
-  context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
+  request->buffer = 0u;
+
+  gl_->GenBuffers(1, &request->buffer);
+  gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer);
+  gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
+                  bytes_per_pixel * dst_size.GetArea(),
+                  NULL,
+                  GL_STREAM_READ);
+
+  request->query = 0u;
+  gl_->GenQueriesEXT(1, &request->query);
+  gl_->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, request->query);
+  gl_->ReadPixels(0,
+                  0,
+                  dst_size.width(),
+                  dst_size.height(),
+                  format,
+                  type,
+                  NULL);
+  gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM);
+  gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
   context_support_->SignalQuery(
       request->query,
-      base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), request));
+      base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(),
+                 request, bytes_per_pixel));
 }
 
-
 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
-    WebGLId src_texture,
+    GLuint src_texture,
     const gfx::Size& src_size,
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     unsigned char* out,
+    const SkColorType out_color_type,
     const base::Callback<void(bool)>& callback,
     GLHelper::ScalerQuality quality) {
-  WebGLId texture = ScaleTexture(src_texture,
-                                 src_size,
-                                 src_subrect,
+  GLenum format, type;
+  size_t bytes_per_pixel;
+  SkColorType readback_color_type = out_color_type;
+  // Single-component textures are not supported by all GPUs, so  we implement
+  // kAlpha_8_SkColorType support here via a special encoding (see below) using
+  // a 32-bit texture to represent an 8-bit image.
+  // Thus we use generic 32-bit readback in this case.
+  if (out_color_type == kAlpha_8_SkColorType) {
+    readback_color_type = kRGBA_8888_SkColorType;
+  }
+
+  FormatSupport supported = GetReadbackConfig(
+      readback_color_type, true, &format, &type, &bytes_per_pixel);
+
+  if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
+    callback.Run(false);
+    return;
+  }
+
+  GLuint texture = src_texture;
+
+  // Scale texture if needed
+  // Optimization: SCALER_QUALITY_FAST is just a single bilinear pass, which we
+  // can do just as well in EncodeTextureAsGrayscale, which we will do if
+  // out_color_type is kAlpha_8_SkColorType, so let's skip the scaling step
+  // in that case.
+  bool scale_texture = out_color_type != kAlpha_8_SkColorType ||
+                       quality != GLHelper::SCALER_QUALITY_FAST;
+  if (scale_texture) {
+    // Don't swizzle during the scale step for kAlpha_8_SkColorType.
+    // We will swizzle in the encode step below if needed.
+    bool scale_swizzle = out_color_type == kAlpha_8_SkColorType
+                             ? false
+                             : supported == GLHelperReadbackSupport::SWIZZLE;
+    texture =
+        ScaleTexture(src_texture,
+                     src_size,
+                     src_subrect,
+                     dst_size,
+                     true,
+                     scale_swizzle,
+                     out_color_type == kAlpha_8_SkColorType ? kN32_SkColorType
+                                                            : out_color_type,
+                     quality);
+    DCHECK(texture);
+  }
+
+  gfx::Size readback_texture_size = dst_size;
+  // Encode texture to grayscale if needed.
+  if (out_color_type == kAlpha_8_SkColorType) {
+    // Do the vertical flip here if we haven't already done it when we scaled
+    // the texture.
+    bool encode_as_grayscale_vertical_flip = !scale_texture;
+    // EncodeTextureAsGrayscale by default creates a texture which should be
+    // read back as RGBA, so need to swizzle if the readback format is BGRA.
+    bool encode_as_grayscale_swizzle = format == GL_BGRA_EXT;
+    GLuint tmp_texture =
+        EncodeTextureAsGrayscale(texture,
                                  dst_size,
-                                 true,
-#if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
-                                 true,
-#else
-                                 false,
-#endif
-                                 quality);
-  ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer());
-  ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_,
+                                 &readback_texture_size,
+                                 encode_as_grayscale_vertical_flip,
+                                 encode_as_grayscale_swizzle);
+    // If the scaled texture was created - delete it
+    if (scale_texture)
+      gl_->DeleteTextures(1, &texture);
+    texture = tmp_texture;
+    DCHECK(texture);
+  }
+
+  // Readback the pixels of the resulting texture
+  ScopedFramebuffer dst_framebuffer(gl_);
+  ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
                                                              dst_framebuffer);
-  ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
-  context_->framebufferTexture2D(GL_FRAMEBUFFER,
-                                 GL_COLOR_ATTACHMENT0,
-                                 GL_TEXTURE_2D,
-                                 texture,
-                                 0);
-  ReadbackAsync(dst_size,
-                dst_size.width() * 4,
-                dst_size.width() * 4,
+  ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
+  gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
+                            GL_COLOR_ATTACHMENT0,
+                            GL_TEXTURE_2D,
+                            texture,
+                            0);
+
+  int32 bytes_per_row = out_color_type == kAlpha_8_SkColorType
+                            ? dst_size.width()
+                            : dst_size.width() * bytes_per_pixel;
+
+  ReadbackAsync(readback_texture_size,
+                bytes_per_row,
+                bytes_per_row,
                 out,
+                format,
+                type,
+                bytes_per_pixel,
                 callback);
-  context_->deleteTexture(texture);
+  gl_->DeleteTextures(1, &texture);
 }
 
 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(
-    WebGLId texture,
+    GLuint texture,
     const gfx::Rect& src_rect,
-    unsigned char* out) {
-  ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer());
-  ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_,
+    unsigned char* out,
+    SkColorType color_type) {
+  GLenum format, type;
+  size_t bytes_per_pixel;
+  FormatSupport supported =
+      GetReadbackConfig(color_type, false, &format, &type, &bytes_per_pixel);
+  if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
+    return;
+  }
+
+  ScopedFramebuffer dst_framebuffer(gl_);
+  ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
                                                              dst_framebuffer);
-  ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
-  context_->framebufferTexture2D(GL_FRAMEBUFFER,
-                                 GL_COLOR_ATTACHMENT0,
-                                 GL_TEXTURE_2D,
-                                 texture,
-                                 0);
-  context_->readPixels(src_rect.x(),
-                       src_rect.y(),
-                       src_rect.width(),
-                       src_rect.height(),
-                       GL_RGBA,
-                       GL_UNSIGNED_BYTE,
-                       out);
+  ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
+  gl_->FramebufferTexture2D(
+      GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+  gl_->ReadPixels(src_rect.x(),
+                  src_rect.y(),
+                  src_rect.width(),
+                  src_rect.height(),
+                  format,
+                  type,
+                  out);
+}
+
+void GLHelper::CopyTextureToImpl::ReadbackTextureAsync(
+    GLuint texture,
+    const gfx::Size& dst_size,
+    unsigned char* out,
+    SkColorType color_type,
+    const base::Callback<void(bool)>& callback) {
+  GLenum format, type;
+  size_t bytes_per_pixel;
+  FormatSupport supported =
+      GetReadbackConfig(color_type, false, &format, &type, &bytes_per_pixel);
+  if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
+    callback.Run(false);
+    return;
+  }
+
+  ScopedFramebuffer dst_framebuffer(gl_);
+  ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
+                                                             dst_framebuffer);
+  ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
+  gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
+                            GL_COLOR_ATTACHMENT0,
+                            GL_TEXTURE_2D,
+                            texture,
+                            0);
+  ReadbackAsync(dst_size,
+                dst_size.width() * bytes_per_pixel,
+                dst_size.width() * bytes_per_pixel,
+                out,
+                format,
+                type,
+                bytes_per_pixel,
+                callback);
 }
 
-WebKit::WebGLId GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
-    WebGLId src_texture,
+GLuint GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
+    GLuint src_texture,
     const gfx::Size& src_size,
     const gfx::Size& dst_size,
     bool vertically_flip_texture,
@@ -480,10 +677,12 @@ WebKit::WebGLId GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
                       dst_size,
                       vertically_flip_texture,
                       false,
+                      kRGBA_8888_SkColorType,  // GL_RGBA
                       quality);
 }
 
-void GLHelper::CopyTextureToImpl::ReadbackDone(Request* finished_request) {
+void GLHelper::CopyTextureToImpl::ReadbackDone(Request* finished_request,
+                                               int bytes_per_pixel) {
   TRACE_EVENT0("mirror",
                "GLHelper::CopyTextureToImpl::CheckReadbackFramebufferComplete");
   finished_request->done = true;
@@ -498,46 +697,43 @@ void GLHelper::CopyTextureToImpl::ReadbackDone(Request* finished_request) {
 
     bool result = false;
     if (request->buffer != 0) {
-      context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
-                           request->buffer);
-      unsigned char* data = static_cast<unsigned char *>(
-          context_->mapBufferCHROMIUM(
-              GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY));
+      gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer);
+      unsigned char* data = static_cast<unsigned char*>(gl_->MapBufferCHROMIUM(
+          GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY));
       if (data) {
         result = true;
-        if (request->bytes_per_row == request->size.width() * 4 &&
+        if (request->bytes_per_row == request->size.width() * bytes_per_pixel &&
             request->bytes_per_row == request->row_stride_bytes) {
-          memcpy(request->pixels, data, request->size.GetArea() * 4);
+          memcpy(request->pixels, data,
+                 request->size.GetArea() * bytes_per_pixel);
         } else {
           unsigned char* out = request->pixels;
           for (int y = 0; y < request->size.height(); y++) {
             memcpy(out, data, request->bytes_per_row);
             out += request->row_stride_bytes;
-            data += request->size.width() * 4;
+            data += request->size.width() * bytes_per_pixel;
           }
         }
-        context_->unmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM);
+        gl_->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM);
       }
-      context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
+      gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
     }
-
     FinishRequest(request, result);
   }
 }
 
-void GLHelper::CopyTextureToImpl::FinishRequest(Request* request,
-                                                bool result) {
+void GLHelper::CopyTextureToImpl::FinishRequest(Request* request, bool result) {
   TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::FinishRequest");
   DCHECK(request_queue_.front() == request);
   request_queue_.pop();
   request->callback.Run(result);
-  ScopedFlush flush(context_);
+  ScopedFlush flush(gl_);
   if (request->query != 0) {
-    context_->deleteQueryEXT(request->query);
+    gl_->DeleteQueriesEXT(1, &request->query);
     request->query = 0;
   }
   if (request->buffer != 0) {
-    context_->deleteBuffer(request->buffer);
+    gl_->DeleteBuffers(1, &request->buffer);
     request->buffer = 0;
   }
   delete request;
@@ -550,31 +746,41 @@ void GLHelper::CopyTextureToImpl::CancelRequests() {
   }
 }
 
-GLHelper::GLHelper(WebKit::WebGraphicsContext3D* context,
-                   gpu::ContextSupport* context_support)
-    : context_(context),
-      context_support_(context_support) {
+FormatSupport GLHelper::CopyTextureToImpl::GetReadbackConfig(
+    SkColorType color_type,
+    bool can_swizzle,
+    GLenum* format,
+    GLenum* type,
+    size_t* bytes_per_pixel) {
+  return helper_->readback_support_->GetReadbackConfig(
+      color_type, can_swizzle, format, type, bytes_per_pixel);
 }
 
-GLHelper::~GLHelper() {
-}
+GLHelper::GLHelper(GLES2Interface* gl, gpu::ContextSupport* context_support)
+    : gl_(gl),
+      context_support_(context_support),
+      readback_support_(new GLHelperReadbackSupport(gl)) {}
+
+GLHelper::~GLHelper() {}
 
 void GLHelper::CropScaleReadbackAndCleanTexture(
-    WebGLId src_texture,
+    GLuint src_texture,
     const gfx::Size& src_size,
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     unsigned char* out,
-    const base::Callback<void(bool)>& callback) {
+    const SkColorType out_color_type,
+    const base::Callback<void(bool)>& callback,
+    GLHelper::ScalerQuality quality) {
   InitCopyTextToImpl();
-  copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(
-      src_texture,
-      src_size,
-      src_subrect,
-      dst_size,
-      out,
-      callback,
-      GLHelper::SCALER_QUALITY_FAST);
+  copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(src_texture,
+                                                          src_size,
+                                                          src_subrect,
+                                                          dst_size,
+                                                          out,
+                                                          out_color_type,
+                                                          callback,
+                                                          quality);
 }
 
 void GLHelper::CropScaleReadbackAndCleanMailbox(
@@ -584,153 +790,203 @@ void GLHelper::CropScaleReadbackAndCleanMailbox(
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     unsigned char* out,
-    const base::Callback<void(bool)>& callback) {
-  WebGLId mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point);
-  CropScaleReadbackAndCleanTexture(
-      mailbox_texture, src_size, src_subrect, dst_size, out, callback);
-  context_->deleteTexture(mailbox_texture);
+    const SkColorType out_color_type,
+    const base::Callback<void(bool)>& callback,
+    GLHelper::ScalerQuality quality) {
+  GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point);
+  CropScaleReadbackAndCleanTexture(mailbox_texture,
+                                   src_size,
+                                   src_subrect,
+                                   dst_size,
+                                   out,
+                                   out_color_type,
+                                   callback,
+                                   quality);
+  gl_->DeleteTextures(1, &mailbox_texture);
 }
 
-void GLHelper::ReadbackTextureSync(WebKit::WebGLId texture,
+void GLHelper::ReadbackTextureSync(GLuint texture,
                                    const gfx::Rect& src_rect,
-                                   unsigned char* out) {
+                                   unsigned char* out,
+                                   SkColorType format) {
   InitCopyTextToImpl();
-  copy_texture_to_impl_->ReadbackTextureSync(texture,
-                                             src_rect,
-                                             out);
+  copy_texture_to_impl_->ReadbackTextureSync(texture, src_rect, out, format);
 }
 
-WebKit::WebGLId GLHelper::CopyTexture(WebKit::WebGLId texture,
-                                      const gfx::Size& size) {
+void GLHelper::ReadbackTextureAsync(
+    GLuint texture,
+    const gfx::Size& dst_size,
+    unsigned char* out,
+    SkColorType color_type,
+    const base::Callback<void(bool)>& callback) {
+  InitCopyTextToImpl();
+  copy_texture_to_impl_->ReadbackTextureAsync(texture,
+                                              dst_size,
+                                              out,
+                                              color_type,
+                                              callback);
+}
+
+GLuint GLHelper::CopyTexture(GLuint texture, const gfx::Size& size) {
   InitCopyTextToImpl();
   return copy_texture_to_impl_->CopyAndScaleTexture(
-      texture,
-      size,
-      size,
-      false,
-      GLHelper::SCALER_QUALITY_FAST);
+      texture, size, size, false, GLHelper::SCALER_QUALITY_FAST);
 }
 
-WebKit::WebGLId GLHelper::CopyAndScaleTexture(
-    WebKit::WebGLId texture,
-    const gfx::Size& src_size,
-    const gfx::Size& dst_size,
-    bool vertically_flip_texture,
-    ScalerQuality quality) {
+GLuint GLHelper::CopyAndScaleTexture(GLuint texture,
+                                     const gfx::Size& src_size,
+                                     const gfx::Size& dst_size,
+                                     bool vertically_flip_texture,
+                                     ScalerQuality quality) {
   InitCopyTextToImpl();
-  return copy_texture_to_impl_->CopyAndScaleTexture(texture,
-                                                    src_size,
-                                                    dst_size,
-                                                    vertically_flip_texture,
-                                                    quality);
+  return copy_texture_to_impl_->CopyAndScaleTexture(
+      texture, src_size, dst_size, vertically_flip_texture, quality);
 }
 
-WebGLId GLHelper::CompileShaderFromSource(
-    const WebKit::WGC3Dchar* source,
-    WebKit::WGC3Denum type) {
-  ScopedShader shader(context_, context_->createShader(type));
-  context_->shaderSource(shader, source);
-  context_->compileShader(shader);
-  WebKit::WGC3Dint compile_status = 0;
-  context_->getShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
+GLuint GLHelper::CompileShaderFromSource(const GLchar* source, GLenum type) {
+  GLuint shader = gl_->CreateShader(type);
+  GLint length = strlen(source);
+  gl_->ShaderSource(shader, 1, &source, &length);
+  gl_->CompileShader(shader);
+  GLint compile_status = 0;
+  gl_->GetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
   if (!compile_status) {
-    LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8());
+    GLint log_length = 0;
+    gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
+    if (log_length) {
+      scoped_ptr<GLchar[]> log(new GLchar[log_length]);
+      GLsizei returned_log_length = 0;
+      gl_->GetShaderInfoLog(
+          shader, log_length, &returned_log_length, log.get());
+      LOG(ERROR) << std::string(log.get(), returned_log_length);
+    }
+    gl_->DeleteShader(shader);
     return 0;
   }
-  return shader.Detach();
+  return shader;
 }
 
 void GLHelper::InitCopyTextToImpl() {
   // Lazily initialize |copy_texture_to_impl_|
   if (!copy_texture_to_impl_)
     copy_texture_to_impl_.reset(
-        new CopyTextureToImpl(context_, context_support_, this));
+        new CopyTextureToImpl(gl_, context_support_, this));
 }
 
 void GLHelper::InitScalerImpl() {
   // Lazily initialize |scaler_impl_|
   if (!scaler_impl_)
-    scaler_impl_.reset(new GLHelperScaling(context_, this));
+    scaler_impl_.reset(new GLHelperScaling(gl_, this));
 }
 
-WebKit::WGC3Dint GLHelper::MaxDrawBuffers() {
+GLint GLHelper::MaxDrawBuffers() {
   InitCopyTextToImpl();
   return copy_texture_to_impl_->MaxDrawBuffers();
 }
 
-void GLHelper::CopySubBufferDamage(WebKit::WebGLId texture,
-                                   WebKit::WebGLId previous_texture,
+void GLHelper::CopySubBufferDamage(GLuint texture,
+                                   GLuint previous_texture,
                                    const SkRegion& new_damage,
                                    const SkRegion& old_damage) {
   SkRegion region(old_damage);
   if (region.op(new_damage, SkRegion::kDifference_Op)) {
-    ScopedFramebuffer dst_framebuffer(context_,
-                                      context_->createFramebuffer());
-    ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_,
+    ScopedFramebuffer dst_framebuffer(gl_);
+    ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
                                                                dst_framebuffer);
-    ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
-    context_->framebufferTexture2D(GL_FRAMEBUFFER,
-                                   GL_COLOR_ATTACHMENT0,
-                                   GL_TEXTURE_2D,
-                                   previous_texture,
-                                   0);
+    ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
+    gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
+                              GL_COLOR_ATTACHMENT0,
+                              GL_TEXTURE_2D,
+                              previous_texture,
+                              0);
     for (SkRegion::Iterator it(region); !it.done(); it.next()) {
       const SkIRect& rect = it.rect();
-      context_->copyTexSubImage2D(GL_TEXTURE_2D, 0,
-                                  rect.x(), rect.y(),
-                                  rect.x(), rect.y(),
-                                  rect.width(), rect.height());
+      gl_->CopyTexSubImage2D(GL_TEXTURE_2D,
+                             0,
+                             rect.x(),
+                             rect.y(),
+                             rect.x(),
+                             rect.y(),
+                             rect.width(),
+                             rect.height());
     }
-    context_->flush();
+    gl_->Flush();
   }
 }
 
-WebKit::WebGLId GLHelper::CreateTexture() {
-  WebKit::WebGLId texture = context_->createTexture();
-  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_,
-                                                             texture);
-  context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+GLuint GLHelper::CreateTexture() {
+  GLuint texture = 0u;
+  gl_->GenTextures(1, &texture);
+  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
+  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   return texture;
 }
 
-WebKit::WebGLId GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
-                                                  uint32 sync_point) {
+void GLHelper::DeleteTexture(GLuint texture_id) {
+  gl_->DeleteTextures(1, &texture_id);
+}
+
+uint32 GLHelper::InsertSyncPoint() { return gl_->InsertSyncPointCHROMIUM(); }
+
+void GLHelper::WaitSyncPoint(uint32 sync_point) {
+  gl_->WaitSyncPointCHROMIUM(sync_point);
+}
+
+gpu::MailboxHolder GLHelper::ProduceMailboxHolderFromTexture(
+    GLuint texture_id) {
+  gpu::Mailbox mailbox;
+  gl_->GenMailboxCHROMIUM(mailbox.name);
+  gl_->ProduceTextureDirectCHROMIUM(texture_id, GL_TEXTURE_2D, mailbox.name);
+  return gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, InsertSyncPoint());
+}
+
+GLuint GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
+                                         uint32 sync_point) {
   if (mailbox.IsZero())
     return 0;
   if (sync_point)
-    context_->waitSyncPoint(sync_point);
-  WebKit::WebGLId texture = CreateTexture();
-  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_,
-                                                             texture);
-  context_->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+    WaitSyncPoint(sync_point);
+  GLuint texture =
+      gl_->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
   return texture;
 }
 
-void GLHelper::ResizeTexture(WebKit::WebGLId texture, const gfx::Size& size) {
-  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
-  context_->texImage2D(GL_TEXTURE_2D, 0, GL_RGB,
-                       size.width(), size.height(), 0,
-                       GL_RGB, GL_UNSIGNED_BYTE, NULL);
+void GLHelper::ResizeTexture(GLuint texture, const gfx::Size& size) {
+  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
+  gl_->TexImage2D(GL_TEXTURE_2D,
+                  0,
+                  GL_RGB,
+                  size.width(),
+                  size.height(),
+                  0,
+                  GL_RGB,
+                  GL_UNSIGNED_BYTE,
+                  NULL);
+}
+
+void GLHelper::CopyTextureSubImage(GLuint texture, const gfx::Rect& rect) {
+  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
+  gl_->CopyTexSubImage2D(GL_TEXTURE_2D,
+                         0,
+                         rect.x(),
+                         rect.y(),
+                         rect.x(),
+                         rect.y(),
+                         rect.width(),
+                         rect.height());
 }
 
-void GLHelper::CopyTextureSubImage(WebKit::WebGLId texture,
-                                   const gfx::Rect& rect) {
-  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
-  context_->copyTexSubImage2D(GL_TEXTURE_2D, 0,
-                              rect.x(), rect.y(),
-                              rect.x(), rect.y(), rect.width(), rect.height());
+void GLHelper::CopyTextureFullImage(GLuint texture, const gfx::Size& size) {
+  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
+  gl_->CopyTexImage2D(
+      GL_TEXTURE_2D, 0, GL_RGB, 0, 0, size.width(), size.height(), 0);
 }
 
-void GLHelper::CopyTextureFullImage(WebKit::WebGLId texture,
-                                    const gfx::Size& size) {
-  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture);
-  context_->copyTexImage2D(GL_TEXTURE_2D, 0,
-                           GL_RGB,
-                           0, 0,
-                           size.width(), size.height(), 0);
+void GLHelper::Flush() {
+  gl_->Flush();
 }
 
 void GLHelper::CopyTextureToImpl::ReadbackPlane(
@@ -739,32 +995,34 @@ void GLHelper::CopyTextureToImpl::ReadbackPlane(
     int plane,
     int size_shift,
     const gfx::Rect& dst_subrect,
+    ReadbackSwizzle swizzle,
     const base::Callback<void(bool)>& callback) {
-  context_->bindFramebuffer(GL_FRAMEBUFFER, source->framebuffer());
+  gl_->BindFramebuffer(GL_FRAMEBUFFER, source->framebuffer());
   size_t offset = target->stride(plane) * (dst_subrect.y() >> size_shift) +
       (dst_subrect.x() >> size_shift);
-  ReadbackAsync(
-      source->size(),
-      dst_subrect.width() >> size_shift,
-      target->stride(plane),
-      target->data(plane) + offset,
-      callback);
+  ReadbackAsync(source->size(),
+                dst_subrect.width() >> size_shift,
+                target->stride(plane),
+                target->data(plane) + offset,
+                (swizzle == kSwizzleBGRA) ? GL_BGRA_EXT : GL_RGBA,
+                GL_UNSIGNED_BYTE,
+                4,
+                callback);
 }
 
 const float GLHelper::CopyTextureToImpl::kRGBtoYColorWeights[] = {
-  0.257f, 0.504f, 0.098f, 0.0625f
-};
+    0.257f, 0.504f, 0.098f, 0.0625f};
 const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = {
-  -0.148f, -0.291f, 0.439f, 0.5f
-};
+    -0.148f, -0.291f, 0.439f, 0.5f};
 const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = {
-  0.439f, -0.368f, -0.071f, 0.5f
-};
+    0.439f, -0.368f, -0.071f, 0.5f};
+const float GLHelper::CopyTextureToImpl::kRGBtoGrayscaleColorWeights[] = {
+    0.213f, 0.715f, 0.072f, 0.0f};
 
 // YUV readback constructors. Initiates the main scaler pipeline and
 // one planar scaler for each of the Y, U and V planes.
 GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
-    WebGraphicsContext3D* context,
+    GLES2Interface* gl,
     CopyTextureToImpl* copy_impl,
     GLHelperScaling* scaler_impl,
     GLHelper::ScalerQuality quality,
@@ -772,45 +1030,55 @@ GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     const gfx::Rect& dst_subrect,
-    bool flip_vertically)
-    : context_(context),
+    bool flip_vertically,
+    ReadbackSwizzle swizzle)
+    : gl_(gl),
       copy_impl_(copy_impl),
       dst_size_(dst_size),
       dst_subrect_(dst_subrect),
-      scaler_(context, scaler_impl->CreateScaler(
-          quality,
-          src_size,
-          src_subrect,
-          dst_subrect.size(),
-          flip_vertically,
-          false)),
-      y_(context, scaler_impl->CreatePlanarScaler(
-          dst_subrect.size(),
-          gfx::Rect(0, 0,
-                    (dst_subrect.width() + 3) & ~3,
-                    dst_subrect.height()),
-          gfx::Size((dst_subrect.width() + 3) / 4,
-                    dst_subrect.height()),
-          false,
-          kRGBtoYColorWeights)),
-      u_(context, scaler_impl->CreatePlanarScaler(
-          dst_subrect.size(),
-          gfx::Rect(0, 0,
-                    (dst_subrect.width() + 7) & ~7,
-                    (dst_subrect.height() + 1) & ~1),
-          gfx::Size((dst_subrect.width() + 7) / 8,
-                    (dst_subrect.height() + 1) / 2),
-          false,
-          kRGBtoUColorWeights)),
-      v_(context, scaler_impl->CreatePlanarScaler(
-          dst_subrect.size(),
-          gfx::Rect(0, 0,
-                    (dst_subrect.width() + 7) & ~7,
-                    (dst_subrect.height() + 1) & ~1),
-          gfx::Size((dst_subrect.width() + 7) / 8,
-                    (dst_subrect.height() + 1) / 2),
-          false,
-          kRGBtoVColorWeights)) {
+      swizzle_(swizzle),
+      scaler_(gl,
+              scaler_impl->CreateScaler(quality,
+                                        src_size,
+                                        src_subrect,
+                                        dst_subrect.size(),
+                                        flip_vertically,
+                                        false)),
+      y_(gl,
+         scaler_impl->CreatePlanarScaler(
+             dst_subrect.size(),
+             gfx::Rect(0,
+                       0,
+                       (dst_subrect.width() + 3) & ~3,
+                       dst_subrect.height()),
+             gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
+             false,
+             (swizzle == kSwizzleBGRA),
+             kRGBtoYColorWeights)),
+      u_(gl,
+         scaler_impl->CreatePlanarScaler(
+             dst_subrect.size(),
+             gfx::Rect(0,
+                       0,
+                       (dst_subrect.width() + 7) & ~7,
+                       (dst_subrect.height() + 1) & ~1),
+             gfx::Size((dst_subrect.width() + 7) / 8,
+                       (dst_subrect.height() + 1) / 2),
+             false,
+             (swizzle == kSwizzleBGRA),
+             kRGBtoUColorWeights)),
+      v_(gl,
+         scaler_impl->CreatePlanarScaler(
+             dst_subrect.size(),
+             gfx::Rect(0,
+                       0,
+                       (dst_subrect.width() + 7) & ~7,
+                       (dst_subrect.height() + 1) & ~1),
+             gfx::Size((dst_subrect.width() + 7) / 8,
+                       (dst_subrect.height() + 1) / 2),
+             false,
+             (swizzle == kSwizzleBGRA),
+             kRGBtoVColorWeights)) {
   DCHECK(!(dst_size.width() & 1));
   DCHECK(!(dst_size.height() & 1));
   DCHECK(!(dst_subrect.width() & 1));
@@ -831,12 +1099,12 @@ void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV(
     uint32 sync_point,
     const scoped_refptr<media::VideoFrame>& target,
     const base::Callback<void(bool)>& callback) {
-  WebGLId mailbox_texture =
+  GLuint mailbox_texture =
       copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point);
 
   // Scale texture to right size.
   scaler_.Scale(mailbox_texture);
-  context_->deleteTexture(mailbox_texture);
+  gl_->DeleteTextures(1, &mailbox_texture);
 
   // Convert the scaled texture in to Y, U and V planes.
   y_.Scale(scaler_.texture());
@@ -857,29 +1125,31 @@ void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV(
                             media::VideoFrame::kYPlane,
                             0,
                             dst_subrect_,
+                            swizzle_,
                             base::Bind(&nullcallback));
   copy_impl_->ReadbackPlane(u_.texture_and_framebuffer(),
                             target,
                             media::VideoFrame::kUPlane,
                             1,
                             dst_subrect_,
+                            swizzle_,
                             base::Bind(&nullcallback));
-  copy_impl_->ReadbackPlane(v_.texture_and_framebuffer(),
-                            target,
-                            media::VideoFrame::kVPlane,
-                            1,
-                            dst_subrect_,
-                            base::Bind(&CallbackKeepingVideoFrameAlive,
-                                       target,
-                                       callback));
-  context_->bindFramebuffer(GL_FRAMEBUFFER, 0);
-  media::LetterboxYUV(target, dst_subrect_);
+  copy_impl_->ReadbackPlane(
+      v_.texture_and_framebuffer(),
+      target,
+      media::VideoFrame::kVPlane,
+      1,
+      dst_subrect_,
+      swizzle_,
+      base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
+  gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
+  media::LetterboxYUV(target.get(), dst_subrect_);
 }
 
 // YUV readback constructors. Initiates the main scaler pipeline and
 // one planar scaler for each of the Y, U and V planes.
 GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT(
-    WebGraphicsContext3D* context,
+    GLES2Interface* gl,
     CopyTextureToImpl* copy_impl,
     GLHelperScaling* scaler_impl,
     GLHelper::ScalerQuality quality,
@@ -887,56 +1157,58 @@ GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT(
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     const gfx::Rect& dst_subrect,
-    bool flip_vertically)
-    : context_(context),
+    bool flip_vertically,
+    ReadbackSwizzle swizzle)
+    : gl_(gl),
       copy_impl_(copy_impl),
       dst_size_(dst_size),
       dst_subrect_(dst_subrect),
       quality_(quality),
-      scaler_(context, scaler_impl->CreateScaler(
-          quality,
-          src_size,
-          src_subrect,
-          dst_subrect.size(),
-          false,
-          false)),
+      swizzle_(swizzle),
+      scaler_(gl,
+              scaler_impl->CreateScaler(quality,
+                                        src_size,
+                                        src_subrect,
+                                        dst_subrect.size(),
+                                        false,
+                                        false)),
       pass1_shader_(scaler_impl->CreateYuvMrtShader(
           dst_subrect.size(),
-          gfx::Rect(0, 0,
-                    (dst_subrect.width() + 3) & ~3,
-                    dst_subrect.height()),
-          gfx::Size((dst_subrect.width() + 3) / 4,
-                    dst_subrect.height()),
+          gfx::Rect(0, 0, (dst_subrect.width() + 3) & ~3, dst_subrect.height()),
+          gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
           flip_vertically,
+          (swizzle == kSwizzleBGRA),
           GLHelperScaling::SHADER_YUV_MRT_PASS1)),
       pass2_shader_(scaler_impl->CreateYuvMrtShader(
-          gfx::Size((dst_subrect.width() + 3) / 4,
-                    dst_subrect.height()),
-          gfx::Rect(0, 0,
+          gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
+          gfx::Rect(0,
+                    0,
                     (dst_subrect.width() + 7) / 8 * 2,
                     dst_subrect.height()),
           gfx::Size((dst_subrect.width() + 7) / 8,
                     (dst_subrect.height() + 1) / 2),
           false,
+          (swizzle == kSwizzleBGRA),
           GLHelperScaling::SHADER_YUV_MRT_PASS2)),
-      y_(context, gfx::Size((dst_subrect.width() + 3) / 4,
-                            dst_subrect.height())),
-      uv_(context, context->createTexture()),
-      u_(context, gfx::Size((dst_subrect.width() + 7) / 8,
-                            (dst_subrect.height() + 1) / 2)),
-      v_(context, gfx::Size((dst_subrect.width() + 7) / 8,
-                            (dst_subrect.height() + 1) / 2)) {
-
-  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context, uv_);
-  context->texImage2D(GL_TEXTURE_2D,
-                      0,
-                      GL_RGBA,
-                      (dst_subrect.width() + 3) / 4,
-                      dst_subrect.height(),
-                      0,
-                      GL_RGBA,
-                      GL_UNSIGNED_BYTE,
-                      NULL);
+      y_(gl, gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height())),
+      uv_(gl),
+      u_(gl,
+         gfx::Size((dst_subrect.width() + 7) / 8,
+                   (dst_subrect.height() + 1) / 2)),
+      v_(gl,
+         gfx::Size((dst_subrect.width() + 7) / 8,
+                   (dst_subrect.height() + 1) / 2)) {
+
+  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl, uv_);
+  gl->TexImage2D(GL_TEXTURE_2D,
+                 0,
+                 GL_RGBA,
+                 (dst_subrect.width() + 3) / 4,
+                 dst_subrect.height(),
+                 0,
+                 GL_RGBA,
+                 GL_UNSIGNED_BYTE,
+                 NULL);
 
   DCHECK(!(dst_size.width() & 1));
   DCHECK(!(dst_size.height() & 1));
@@ -951,10 +1223,10 @@ void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV(
     uint32 sync_point,
     const scoped_refptr<media::VideoFrame>& target,
     const base::Callback<void(bool)>& callback) {
-  WebGLId mailbox_texture =
+  GLuint mailbox_texture =
       copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point);
 
-  WebGLId texture;
+  GLuint texture;
   if (quality_ == GLHelper::SCALER_QUALITY_FAST) {
     // Optimization: SCALER_QUALITY_FAST is just a single bilinear
     // pass, which pass1_shader_ can do just as well, so let's skip
@@ -966,14 +1238,13 @@ void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV(
     texture = scaler_.texture();
   }
 
-
-  std::vector<WebKit::WebGLId> outputs(2);
+  std::vector<GLuint> outputs(2);
   // Convert the scaled texture in to Y, U and V planes.
   outputs[0] = y_.texture();
   outputs[1] = uv_;
   pass1_shader_->Execute(texture, outputs);
 
-  context_->deleteTexture(mailbox_texture);
+  gl_->DeleteTextures(1, &mailbox_texture);
 
   outputs[0] = u_.texture();
   outputs[1] = v_.texture();
@@ -992,27 +1263,38 @@ void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV(
                             media::VideoFrame::kYPlane,
                             0,
                             dst_subrect_,
+                            swizzle_,
                             base::Bind(&nullcallback));
   copy_impl_->ReadbackPlane(&u_,
                             target,
                             media::VideoFrame::kUPlane,
                             1,
                             dst_subrect_,
+                            swizzle_,
                             base::Bind(&nullcallback));
-  copy_impl_->ReadbackPlane(&v_,
-                            target,
-                            media::VideoFrame::kVPlane,
-                            1,
-                            dst_subrect_,
-                            base::Bind(&CallbackKeepingVideoFrameAlive,
-                                       target,
-                                       callback));
-  context_->bindFramebuffer(GL_FRAMEBUFFER, 0);
-  media::LetterboxYUV(target, dst_subrect_);
+  copy_impl_->ReadbackPlane(
+      &v_,
+      target,
+      media::VideoFrame::kVPlane,
+      1,
+      dst_subrect_,
+      swizzle_,
+      base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
+  gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
+  media::LetterboxYUV(target.get(), dst_subrect_);
 }
 
-ReadbackYUVInterface*
-GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
+bool GLHelper::IsReadbackConfigSupported(SkColorType color_type) {
+  DCHECK(readback_support_.get());
+  GLenum format, type;
+  size_t bytes_per_pixel;
+  FormatSupport support = readback_support_->GetReadbackConfig(
+      color_type, false, &format, &type, &bytes_per_pixel);
+
+  return (support == GLHelperReadbackSupport::SUPPORTED);
+}
+
+ReadbackYUVInterface* GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
     GLHelper::ScalerQuality quality,
     const gfx::Size& src_size,
     const gfx::Rect& src_subrect,
@@ -1021,32 +1303,44 @@ GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
     bool flip_vertically,
     bool use_mrt) {
   helper_->InitScalerImpl();
+  // Just query if the best readback configuration needs a swizzle In
+  // ReadbackPlane() we will choose GL_RGBA/GL_BGRA_EXT based on swizzle
+  GLenum format, type;
+  size_t bytes_per_pixel;
+  FormatSupport supported = GetReadbackConfig(
+      kRGBA_8888_SkColorType, true, &format, &type, &bytes_per_pixel);
+  DCHECK((format == GL_RGBA || format == GL_BGRA_EXT) &&
+         type == GL_UNSIGNED_BYTE);
+
+  ReadbackSwizzle swizzle = kSwizzleNone;
+  if (supported == GLHelperReadbackSupport::SWIZZLE)
+    swizzle = kSwizzleBGRA;
+
   if (max_draw_buffers_ >= 2 && use_mrt) {
-    return new ReadbackYUV_MRT(
-        context_,
-        this,
-        helper_->scaler_impl_.get(),
-        quality,
-        src_size,
-        src_subrect,
-        dst_size,
-        dst_subrect,
-        flip_vertically);
+    return new ReadbackYUV_MRT(gl_,
+                               this,
+                               helper_->scaler_impl_.get(),
+                               quality,
+                               src_size,
+                               src_subrect,
+                               dst_size,
+                               dst_subrect,
+                               flip_vertically,
+                               swizzle);
   }
-  return new ReadbackYUVImpl(
-      context_,
-      this,
-      helper_->scaler_impl_.get(),
-      quality,
-      src_size,
-      src_subrect,
-      dst_size,
-      dst_subrect,
-      flip_vertically);
+  return new ReadbackYUVImpl(gl_,
+                             this,
+                             helper_->scaler_impl_.get(),
+                             quality,
+                             src_size,
+                             src_subrect,
+                             dst_size,
+                             dst_subrect,
+                             flip_vertically,
+                             swizzle);
 }
 
-ReadbackYUVInterface*
-GLHelper::CreateReadbackPipelineYUV(
+ReadbackYUVInterface* GLHelper::CreateReadbackPipelineYUV(
     ScalerQuality quality,
     const gfx::Size& src_size,
     const gfx::Rect& src_subrect,
@@ -1055,14 +1349,13 @@ GLHelper::CreateReadbackPipelineYUV(
     bool flip_vertically,
     bool use_mrt) {
   InitCopyTextToImpl();
-  return copy_texture_to_impl_->CreateReadbackPipelineYUV(
-      quality,
-      src_size,
-      src_subrect,
-      dst_size,
-      dst_subrect,
-      flip_vertically,
-      use_mrt);
+  return copy_texture_to_impl_->CreateReadbackPipelineYUV(quality,
+                                                          src_size,
+                                                          src_subrect,
+                                                          dst_size,
+                                                          dst_subrect,
+                                                          flip_vertically,
+                                                          use_mrt);
 }
 
 }  // namespace content