Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / client / gl_helper.cc
index 8d9dbac..8c4a260 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/skia/include/core/SkRegion.h"
@@ -29,6 +31,18 @@ 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 {
@@ -91,6 +105,7 @@ class ScalerHolder {
 }  // namespace
 
 namespace content {
+typedef GLHelperReadbackSupport::FormatSupport FormatSupport;
 
 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates
 // the data needed for it.
@@ -127,19 +142,19 @@ class GLHelper::CopyTextureToImpl
       const gfx::Rect& src_subrect,
       const gfx::Size& dst_size,
       unsigned char* out,
-      const SkBitmap::Config config,
+      const SkColorType out_color_type,
       const base::Callback<void(bool)>& callback,
       GLHelper::ScalerQuality quality);
 
   void ReadbackTextureSync(GLuint texture,
                            const gfx::Rect& src_rect,
                            unsigned char* out,
-                           SkBitmap::Config format);
+                           SkColorType format);
 
   void ReadbackTextureAsync(GLuint texture,
                             const gfx::Size& dst_size,
                             unsigned char* out,
-                            SkBitmap::Config config,
+                            SkColorType color_type,
                             const base::Callback<void(bool)>& callback);
 
   // Reads back bytes from the currently bound frame buffer.
@@ -148,7 +163,9 @@ class GLHelper::CopyTextureToImpl
                      int32 bytes_per_row,     // generally dst_size.width() * 4
                      int32 row_stride_bytes,  // generally dst_size.width() * 4
                      unsigned char* out,
-                     const SkBitmap::Config config,
+                     GLenum format,
+                     GLenum type,
+                     size_t bytes_per_pixel,
                      const base::Callback<void(bool)>& callback);
 
   void ReadbackPlane(TextureFrameBufferPair* source,
@@ -156,6 +173,7 @@ class GLHelper::CopyTextureToImpl
                      int plane,
                      int size_shift,
                      const gfx::Rect& dst_subrect,
+                     ReadbackSwizzle swizzle,
                      const base::Callback<void(bool)>& callback);
 
   GLuint CopyAndScaleTexture(GLuint texture,
@@ -177,6 +195,12 @@ class GLHelper::CopyTextureToImpl
   // 0 if GL_EXT_draw_buffers is not available.
   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.
   // The main thread can cancel the request, before it's handled by the helper
@@ -222,7 +246,8 @@ 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,
@@ -237,6 +262,7 @@ class GLHelper::CopyTextureToImpl
     CopyTextureToImpl* copy_impl_;
     gfx::Size dst_size_;
     gfx::Rect dst_subrect_;
+    ReadbackSwizzle swizzle_;
     ScalerHolder scaler_;
     ScalerHolder y_;
     ScalerHolder u_;
@@ -258,7 +284,8 @@ 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,
@@ -274,6 +301,7 @@ class GLHelper::CopyTextureToImpl
     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_;
@@ -294,9 +322,28 @@ class GLHelper::CopyTextureToImpl
                       const gfx::Size& dst_size,
                       bool vertically_flip_texture,
                       bool swizzle,
-                      SkBitmap::Config config,
+                      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, int bytes_per_pixel);
   void FinishRequest(Request* request, bool result);
@@ -305,6 +352,7 @@ class GLHelper::CopyTextureToImpl
   static const float kRGBtoYColorWeights[];
   static const float kRGBtoUColorWeights[];
   static const float kRGBtoVColorWeights[];
+  static const float kRGBtoGrayscaleColorWeights[];
 
   GLES2Interface* gl_;
   gpu::ContextSupport* context_support_;
@@ -340,14 +388,30 @@ GLuint GLHelper::CopyTextureToImpl::ScaleTexture(
     const gfx::Size& dst_size,
     bool vertically_flip_texture,
     bool swizzle,
-    SkBitmap::Config config,
+    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);
 
-  bool format_support = ((config == SkBitmap::kRGB_565_Config) ||
-                         (config == SkBitmap::kARGB_8888_Config));
-  if (!format_support) {
-    DCHECK(format_support);
-    return 0;
+    // 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,
@@ -356,36 +420,44 @@ GLuint GLHelper::CopyTextureToImpl::ScaleTexture(
                             dst_size,
                             vertically_flip_texture,
                             swizzle));
+  scaler->Scale(src_texture, dst_texture);
+  return dst_texture;
+}
+
+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;
-  // Start with ARGB8888 params as any other format which is not
-  // supported is already asserted above.
-  GLenum format = GL_RGBA , type = GL_UNSIGNED_BYTE;
   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(gl_, dst_texture);
-    switch (config) {
-      case SkBitmap::kARGB_8888_Config:
-        // Do nothing params already set.
-        break;
-      case SkBitmap::kRGB_565_Config:
-        format = GL_RGB;
-        type = GL_UNSIGNED_SHORT_5_6_5;
-        break;
-      default:
-        NOTREACHED();
-        break;
-    }
     gl_->TexImage2D(GL_TEXTURE_2D,
                     0,
-                    format,
-                    dst_size.width(),
-                    dst_size.height(),
+                    GL_RGBA,
+                    encoded_texture_size->width(),
+                    encoded_texture_size->height(),
                     0,
-                    format,
-                    type,
+                    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;
 }
 
@@ -394,37 +466,16 @@ void GLHelper::CopyTextureToImpl::ReadbackAsync(
     int32 bytes_per_row,
     int32 row_stride_bytes,
     unsigned char* out,
-    const SkBitmap::Config config,
+    GLenum format,
+    GLenum type,
+    size_t bytes_per_pixel,
     const base::Callback<void(bool)>& callback) {
-  bool format_support = ((config == SkBitmap::kRGB_565_Config) ||
-                         (config == SkBitmap::kARGB_8888_Config));
-  if (!format_support) {
-    DCHECK(format_support);
-    callback.Run(false);
-    return;
-  }
+  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 = 0u;
-  // Start with ARGB8888 params as any other format which is not
-  // supported is already asserted above.
-  GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
-  int bytes_per_pixel = 4;
-
-  switch (config) {
-    case SkBitmap::kARGB_8888_Config:
-      // Do nothing params already set.
-      break;
-    case SkBitmap::kRGB_565_Config:
-      format = GL_RGB;
-      type = GL_UNSIGNED_SHORT_5_6_5;
-      bytes_per_pixel = 2;
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
+
   gl_->GenBuffers(1, &request->buffer);
   gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer);
   gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
@@ -449,35 +500,86 @@ void GLHelper::CopyTextureToImpl::ReadbackAsync(
       base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(),
                  request, bytes_per_pixel));
 }
+
 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
     GLuint src_texture,
     const gfx::Size& src_size,
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     unsigned char* out,
-    const SkBitmap::Config bitmap_config,
+    const SkColorType out_color_type,
     const base::Callback<void(bool)>& callback,
     GLHelper::ScalerQuality quality) {
-  bool format_support = ((bitmap_config == SkBitmap::kRGB_565_Config) ||
-                         (bitmap_config == SkBitmap::kARGB_8888_Config));
-  if (!format_support) {
-    DCHECK(format_support);
+  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 = ScaleTexture(src_texture,
-                                src_size,
-                                src_subrect,
-                                dst_size,
-                                true,
-#if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
-                                true,
-#else
-                                false,
-#endif
-                                bitmap_config,
-                                quality);
-  DCHECK(texture);
+
+  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,
+                                 &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);
@@ -487,45 +589,41 @@ void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
                             GL_TEXTURE_2D,
                             texture,
                             0);
-  int bytes_per_pixel = 4;
-  switch (bitmap_config) {
-    case SkBitmap::kARGB_8888_Config:
-      // Do nothing params already set.
-      break;
-    case SkBitmap::kRGB_565_Config:
-      bytes_per_pixel = 2;
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-  ReadbackAsync(dst_size,
-                dst_size.width() * bytes_per_pixel,
-                dst_size.width() * bytes_per_pixel,
+
+  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,
-                bitmap_config,
+                format,
+                type,
+                bytes_per_pixel,
                 callback);
   gl_->DeleteTextures(1, &texture);
 }
 
-void GLHelper::CopyTextureToImpl::ReadbackTextureSync(GLuint texture,
-                                                      const gfx::Rect& src_rect,
-                                                      unsigned char* out,
-                                                      SkBitmap::Config config) {
-  DCHECK((config == SkBitmap::kRGB_565_Config) ||
-         (config == SkBitmap::kARGB_8888_Config));
+void GLHelper::CopyTextureToImpl::ReadbackTextureSync(
+    GLuint texture,
+    const gfx::Rect& src_rect,
+    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(gl_, texture);
   gl_->FramebufferTexture2D(
       GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
-  GLenum format = (config == SkBitmap::kRGB_565_Config) ?
-                  GL_RGB :
-                  GL_RGBA;
-  GLenum type = (config == SkBitmap::kRGB_565_Config) ?
-                GL_UNSIGNED_SHORT_5_6_5 :
-                GL_UNSIGNED_BYTE;
   gl_->ReadPixels(src_rect.x(),
                   src_rect.y(),
                   src_rect.width(),
@@ -539,15 +637,17 @@ void GLHelper::CopyTextureToImpl::ReadbackTextureAsync(
     GLuint texture,
     const gfx::Size& dst_size,
     unsigned char* out,
-    SkBitmap::Config config,
+    SkColorType color_type,
     const base::Callback<void(bool)>& callback) {
-  // Only ARGB888 and RGB565 supported as of now.
-  bool format_support = ((config == SkBitmap::kRGB_565_Config) ||
-                         (config == SkBitmap::kARGB_8888_Config));
-  if (!format_support) {
-    DCHECK(format_support);
+  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);
@@ -557,12 +657,13 @@ void GLHelper::CopyTextureToImpl::ReadbackTextureAsync(
                             GL_TEXTURE_2D,
                             texture,
                             0);
-  int bytes_per_pixel = (config == SkBitmap::kRGB_565_Config) ? 2 : 4;
   ReadbackAsync(dst_size,
                 dst_size.width() * bytes_per_pixel,
                 dst_size.width() * bytes_per_pixel,
                 out,
-                config,
+                format,
+                type,
+                bytes_per_pixel,
                 callback);
 }
 
@@ -578,7 +679,7 @@ GLuint GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
                       dst_size,
                       vertically_flip_texture,
                       false,
-                      SkBitmap::kARGB_8888_Config,
+                      kRGBA_8888_SkColorType,  // GL_RGBA
                       quality);
 }
 
@@ -647,11 +748,20 @@ void GLHelper::CopyTextureToImpl::CancelRequests() {
   }
 }
 
+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(GLES2Interface* gl, gpu::ContextSupport* context_support)
     : gl_(gl),
       context_support_(context_support),
-      initialized_565_format_check_(false),
-      support_565_format_(false) {}
+      readback_support_(new GLHelperReadbackSupport(gl)) {}
 
 GLHelper::~GLHelper() {}
 
@@ -661,18 +771,18 @@ void GLHelper::CropScaleReadbackAndCleanTexture(
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     unsigned char* out,
-    const SkBitmap::Config config,
-    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,
-      config,
-      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(
@@ -682,20 +792,25 @@ void GLHelper::CropScaleReadbackAndCleanMailbox(
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     unsigned char* out,
-    const SkBitmap::Config bitmap_config,
-    const base::Callback<void(bool)>& callback) {
+    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,
-      bitmap_config,
-      callback);
+  CropScaleReadbackAndCleanTexture(mailbox_texture,
+                                   src_size,
+                                   src_subrect,
+                                   dst_size,
+                                   out,
+                                   out_color_type,
+                                   callback,
+                                   quality);
   gl_->DeleteTextures(1, &mailbox_texture);
 }
 
 void GLHelper::ReadbackTextureSync(GLuint texture,
                                    const gfx::Rect& src_rect,
                                    unsigned char* out,
-                                   SkBitmap::Config format) {
+                                   SkColorType format) {
   InitCopyTextToImpl();
   copy_texture_to_impl_->ReadbackTextureSync(texture, src_rect, out, format);
 }
@@ -704,13 +819,13 @@ void GLHelper::ReadbackTextureAsync(
     GLuint texture,
     const gfx::Size& dst_size,
     unsigned char* out,
-    SkBitmap::Config config,
+    SkColorType color_type,
     const base::Callback<void(bool)>& callback) {
   InitCopyTextToImpl();
   copy_texture_to_impl_->ReadbackTextureAsync(texture,
                                               dst_size,
                                               out,
-                                              config,
+                                              color_type,
                                               callback);
 }
 
@@ -822,18 +937,12 @@ void GLHelper::WaitSyncPoint(uint32 sync_point) {
   gl_->WaitSyncPointCHROMIUM(sync_point);
 }
 
-gpu::Mailbox GLHelper::ProduceMailboxFromTexture(GLuint texture_id,
-                                                 uint32* sync_point) {
+gpu::MailboxHolder GLHelper::ProduceMailboxHolderFromTexture(
+    GLuint texture_id) {
   gpu::Mailbox mailbox;
   gl_->GenMailboxCHROMIUM(mailbox.name);
-  if (mailbox.IsZero()) {
-    *sync_point = 0;
-    return mailbox;
-  }
-  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture_id);
-  gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
-  *sync_point = InsertSyncPoint();
-  return mailbox;
+  gl_->ProduceTextureDirectCHROMIUM(texture_id, GL_TEXTURE_2D, mailbox.name);
+  return gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, InsertSyncPoint());
 }
 
 GLuint GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
@@ -842,9 +951,8 @@ GLuint GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
     return 0;
   if (sync_point)
     WaitSyncPoint(sync_point);
-  GLuint texture = CreateTexture();
-  content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
-  gl_->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+  GLuint texture =
+      gl_->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
   return texture;
 }
 
@@ -879,44 +987,8 @@ void GLHelper::CopyTextureFullImage(GLuint texture, const gfx::Size& size) {
       GL_TEXTURE_2D, 0, GL_RGB, 0, 0, size.width(), size.height(), 0);
 }
 
-bool GLHelper::CanUseRgb565Readback() {
-  if(initialized_565_format_check_){
-    return support_565_format_;
-  }
-  const int kTestSize = 64;
-  GLuint dst_texture = 0u;
-  gl_->GenTextures(1, &dst_texture);
-  ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
-  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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);
-  gl_->TexImage2D(GL_TEXTURE_2D,
-                  0,
-                  GL_RGB,
-                  kTestSize,
-                  kTestSize,
-                  0,
-                  GL_RGB,
-                  GL_UNSIGNED_SHORT_5_6_5,
-                  NULL);
-  ScopedFramebuffer dst_framebuffer(gl_);
-  ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
-                                                             dst_framebuffer);
-  gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
-                            GL_COLOR_ATTACHMENT0,
-                            GL_TEXTURE_2D,
-                            dst_texture,
-                            0);
-  GLint  ext_format = 0, ext_type = 0;
-  gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &ext_format);
-  gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &ext_type);
-  gl_->DeleteTextures(1, &dst_texture);
-  if ((ext_format == GL_RGB) && (ext_type == GL_UNSIGNED_SHORT_5_6_5)) {
-    support_565_format_ = true;
-  }
-  initialized_565_format_check_ = true;
-  return support_565_format_;
+void GLHelper::Flush() {
+  gl_->Flush();
 }
 
 void GLHelper::CopyTextureToImpl::ReadbackPlane(
@@ -925,6 +997,7 @@ void GLHelper::CopyTextureToImpl::ReadbackPlane(
     int plane,
     int size_shift,
     const gfx::Rect& dst_subrect,
+    ReadbackSwizzle swizzle,
     const base::Callback<void(bool)>& callback) {
   gl_->BindFramebuffer(GL_FRAMEBUFFER, source->framebuffer());
   size_t offset = target->stride(plane) * (dst_subrect.y() >> size_shift) +
@@ -933,7 +1006,9 @@ void GLHelper::CopyTextureToImpl::ReadbackPlane(
                 dst_subrect.width() >> size_shift,
                 target->stride(plane),
                 target->data(plane) + offset,
-                SkBitmap::kARGB_8888_Config,
+                (swizzle == kSwizzleBGRA) ? GL_BGRA_EXT : GL_RGBA,
+                GL_UNSIGNED_BYTE,
+                4,
                 callback);
 }
 
@@ -943,6 +1018,8 @@ const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = {
     -0.148f, -0.291f, 0.439f, 0.5f};
 const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = {
     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.
@@ -955,11 +1032,13 @@ GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     const gfx::Rect& dst_subrect,
-    bool flip_vertically)
+    bool flip_vertically,
+    ReadbackSwizzle swizzle)
     : gl_(gl),
       copy_impl_(copy_impl),
       dst_size_(dst_size),
       dst_subrect_(dst_subrect),
+      swizzle_(swizzle),
       scaler_(gl,
               scaler_impl->CreateScaler(quality,
                                         src_size,
@@ -976,6 +1055,7 @@ GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
                        dst_subrect.height()),
              gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
              false,
+             (swizzle == kSwizzleBGRA),
              kRGBtoYColorWeights)),
       u_(gl,
          scaler_impl->CreatePlanarScaler(
@@ -987,6 +1067,7 @@ GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
              gfx::Size((dst_subrect.width() + 7) / 8,
                        (dst_subrect.height() + 1) / 2),
              false,
+             (swizzle == kSwizzleBGRA),
              kRGBtoUColorWeights)),
       v_(gl,
          scaler_impl->CreatePlanarScaler(
@@ -998,6 +1079,7 @@ GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
              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));
@@ -1045,12 +1127,14 @@ 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(),
@@ -1058,9 +1142,10 @@ void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV(
       media::VideoFrame::kVPlane,
       1,
       dst_subrect_,
+      swizzle_,
       base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
   gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
-  media::LetterboxYUV(target, dst_subrect_);
+  media::LetterboxYUV(target.get(), dst_subrect_);
 }
 
 // YUV readback constructors. Initiates the main scaler pipeline and
@@ -1074,12 +1159,14 @@ GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT(
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     const gfx::Rect& dst_subrect,
-    bool flip_vertically)
+    bool flip_vertically,
+    ReadbackSwizzle swizzle)
     : gl_(gl),
       copy_impl_(copy_impl),
       dst_size_(dst_size),
       dst_subrect_(dst_subrect),
       quality_(quality),
+      swizzle_(swizzle),
       scaler_(gl,
               scaler_impl->CreateScaler(quality,
                                         src_size,
@@ -1092,6 +1179,7 @@ GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT(
           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()),
@@ -1102,6 +1190,7 @@ GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT(
           gfx::Size((dst_subrect.width() + 7) / 8,
                     (dst_subrect.height() + 1) / 2),
           false,
+          (swizzle == kSwizzleBGRA),
           GLHelperScaling::SHADER_YUV_MRT_PASS2)),
       y_(gl, gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height())),
       uv_(gl),
@@ -1176,12 +1265,14 @@ 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_,
@@ -1189,9 +1280,20 @@ void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV(
       media::VideoFrame::kVPlane,
       1,
       dst_subrect_,
+      swizzle_,
       base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
   gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
-  media::LetterboxYUV(target, dst_subrect_);
+  media::LetterboxYUV(target.get(), dst_subrect_);
+}
+
+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(
@@ -1203,6 +1305,19 @@ ReadbackYUVInterface* 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(gl_,
                                this,
@@ -1212,7 +1327,8 @@ ReadbackYUVInterface* GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
                                src_subrect,
                                dst_size,
                                dst_subrect,
-                               flip_vertically);
+                               flip_vertically,
+                               swizzle);
   }
   return new ReadbackYUVImpl(gl_,
                              this,
@@ -1222,7 +1338,8 @@ ReadbackYUVInterface* GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
                              src_subrect,
                              dst_size,
                              dst_subrect,
-                             flip_vertically);
+                             flip_vertically,
+                             swizzle);
 }
 
 ReadbackYUVInterface* GLHelper::CreateReadbackPipelineYUV(