Home | History | Annotate | Download | only in client
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/common/gpu/client/gl_helper.h"
      6 
      7 #include <queue>
      8 #include <string>
      9 
     10 #include "base/bind.h"
     11 #include "base/debug/trace_event.h"
     12 #include "base/lazy_instance.h"
     13 #include "base/logging.h"
     14 #include "base/memory/ref_counted.h"
     15 #include "base/message_loop/message_loop.h"
     16 #include "base/strings/string_util.h"
     17 #include "base/time/time.h"
     18 #include "content/common/gpu/client/gl_helper_readback_support.h"
     19 #include "content/common/gpu/client/gl_helper_scaling.h"
     20 #include "gpu/GLES2/gl2extchromium.h"
     21 #include "gpu/command_buffer/client/context_support.h"
     22 #include "gpu/command_buffer/common/mailbox.h"
     23 #include "gpu/command_buffer/common/mailbox_holder.h"
     24 #include "media/base/video_frame.h"
     25 #include "media/base/video_util.h"
     26 #include "third_party/skia/include/core/SkRegion.h"
     27 #include "ui/gfx/rect.h"
     28 #include "ui/gfx/size.h"
     29 
     30 using gpu::gles2::GLES2Interface;
     31 
     32 namespace {
     33 
     34 class ScopedFlush {
     35  public:
     36   explicit ScopedFlush(gpu::gles2::GLES2Interface* gl) : gl_(gl) {}
     37 
     38   ~ScopedFlush() { gl_->Flush(); }
     39 
     40  private:
     41   gpu::gles2::GLES2Interface* gl_;
     42 
     43   DISALLOW_COPY_AND_ASSIGN(ScopedFlush);
     44 };
     45 
     46 // Helper class for allocating and holding an RGBA texture of a given
     47 // size and an associated framebuffer.
     48 class TextureFrameBufferPair {
     49  public:
     50   TextureFrameBufferPair(GLES2Interface* gl, gfx::Size size)
     51       : texture_(gl), framebuffer_(gl), size_(size) {
     52     content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl, texture_);
     53     gl->TexImage2D(GL_TEXTURE_2D,
     54                    0,
     55                    GL_RGBA,
     56                    size.width(),
     57                    size.height(),
     58                    0,
     59                    GL_RGBA,
     60                    GL_UNSIGNED_BYTE,
     61                    NULL);
     62     content::ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
     63         gl, framebuffer_);
     64     gl->FramebufferTexture2D(
     65         GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_, 0);
     66   }
     67 
     68   GLuint texture() const { return texture_.id(); }
     69   GLuint framebuffer() const { return framebuffer_.id(); }
     70   gfx::Size size() const { return size_; }
     71 
     72  private:
     73   content::ScopedTexture texture_;
     74   content::ScopedFramebuffer framebuffer_;
     75   gfx::Size size_;
     76 
     77   DISALLOW_COPY_AND_ASSIGN(TextureFrameBufferPair);
     78 };
     79 
     80 // Helper class for holding a scaler, a texture for the output of that
     81 // scaler and an associated frame buffer. This is inteded to be used
     82 // when the output of a scaler is to be sent to a readback.
     83 class ScalerHolder {
     84  public:
     85   ScalerHolder(GLES2Interface* gl, content::GLHelper::ScalerInterface* scaler)
     86       : texture_and_framebuffer_(gl, scaler->DstSize()), scaler_(scaler) {}
     87 
     88   void Scale(GLuint src_texture) {
     89     scaler_->Scale(src_texture, texture_and_framebuffer_.texture());
     90   }
     91 
     92   content::GLHelper::ScalerInterface* scaler() const { return scaler_.get(); }
     93   TextureFrameBufferPair* texture_and_framebuffer() {
     94     return &texture_and_framebuffer_;
     95   }
     96   GLuint texture() const { return texture_and_framebuffer_.texture(); }
     97 
     98  private:
     99   TextureFrameBufferPair texture_and_framebuffer_;
    100   scoped_ptr<content::GLHelper::ScalerInterface> scaler_;
    101 
    102   DISALLOW_COPY_AND_ASSIGN(ScalerHolder);
    103 };
    104 
    105 }  // namespace
    106 
    107 namespace content {
    108 
    109 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates
    110 // the data needed for it.
    111 class GLHelper::CopyTextureToImpl
    112     : public base::SupportsWeakPtr<GLHelper::CopyTextureToImpl> {
    113  public:
    114   CopyTextureToImpl(GLES2Interface* gl,
    115                     gpu::ContextSupport* context_support,
    116                     GLHelper* helper)
    117       : gl_(gl),
    118         context_support_(context_support),
    119         helper_(helper),
    120         flush_(gl),
    121         max_draw_buffers_(0) {
    122     const GLubyte* extensions = gl_->GetString(GL_EXTENSIONS);
    123     if (!extensions)
    124       return;
    125     std::string extensions_string =
    126         " " + std::string(reinterpret_cast<const char*>(extensions)) + " ";
    127     if (extensions_string.find(" GL_EXT_draw_buffers ") != std::string::npos) {
    128       gl_->GetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &max_draw_buffers_);
    129     }
    130   }
    131   ~CopyTextureToImpl() { CancelRequests(); }
    132 
    133   GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
    134                                  uint32 sync_point) {
    135     return helper_->ConsumeMailboxToTexture(mailbox, sync_point);
    136   }
    137 
    138   void CropScaleReadbackAndCleanTexture(
    139       GLuint src_texture,
    140       const gfx::Size& src_size,
    141       const gfx::Rect& src_subrect,
    142       const gfx::Size& dst_size,
    143       unsigned char* out,
    144       const SkBitmap::Config config,
    145       const base::Callback<void(bool)>& callback,
    146       GLHelper::ScalerQuality quality);
    147 
    148   void ReadbackTextureSync(GLuint texture,
    149                            const gfx::Rect& src_rect,
    150                            unsigned char* out,
    151                            SkBitmap::Config format);
    152 
    153   void ReadbackTextureAsync(GLuint texture,
    154                             const gfx::Size& dst_size,
    155                             unsigned char* out,
    156                             SkBitmap::Config config,
    157                             const base::Callback<void(bool)>& callback);
    158 
    159   // Reads back bytes from the currently bound frame buffer.
    160   // Note that dst_size is specified in bytes, not pixels.
    161   void ReadbackAsync(const gfx::Size& dst_size,
    162                      int32 bytes_per_row,     // generally dst_size.width() * 4
    163                      int32 row_stride_bytes,  // generally dst_size.width() * 4
    164                      unsigned char* out,
    165                      const SkBitmap::Config config,
    166                      ReadbackSwizzle swizzle,
    167                      const base::Callback<void(bool)>& callback);
    168 
    169   void ReadbackPlane(TextureFrameBufferPair* source,
    170                      const scoped_refptr<media::VideoFrame>& target,
    171                      int plane,
    172                      int size_shift,
    173                      const gfx::Rect& dst_subrect,
    174                      ReadbackSwizzle swizzle,
    175                      const base::Callback<void(bool)>& callback);
    176 
    177   GLuint CopyAndScaleTexture(GLuint texture,
    178                              const gfx::Size& src_size,
    179                              const gfx::Size& dst_size,
    180                              bool vertically_flip_texture,
    181                              GLHelper::ScalerQuality quality);
    182 
    183   ReadbackYUVInterface* CreateReadbackPipelineYUV(
    184       GLHelper::ScalerQuality quality,
    185       const gfx::Size& src_size,
    186       const gfx::Rect& src_subrect,
    187       const gfx::Size& dst_size,
    188       const gfx::Rect& dst_subrect,
    189       bool flip_vertically,
    190       bool use_mrt);
    191 
    192   // Returns the maximum number of draw buffers available,
    193   // 0 if GL_EXT_draw_buffers is not available.
    194   GLint MaxDrawBuffers() const { return max_draw_buffers_; }
    195 
    196   bool IsReadbackConfigSupported(SkBitmap::Config bitmap_config);
    197 
    198  private:
    199   // A single request to CropScaleReadbackAndCleanTexture.
    200   // The main thread can cancel the request, before it's handled by the helper
    201   // thread, by resetting the texture and pixels fields. Alternatively, the
    202   // thread marks that it handles the request by resetting the pixels field
    203   // (meaning it guarantees that the callback with be called).
    204   // In either case, the callback must be called exactly once, and the texture
    205   // must be deleted by the main thread gl.
    206   struct Request {
    207     Request(const gfx::Size& size_,
    208             int32 bytes_per_row_,
    209             int32 row_stride_bytes_,
    210             unsigned char* pixels_,
    211             const base::Callback<void(bool)>& callback_)
    212         : done(false),
    213           size(size_),
    214           bytes_per_row(bytes_per_row_),
    215           row_stride_bytes(row_stride_bytes_),
    216           pixels(pixels_),
    217           callback(callback_),
    218           buffer(0),
    219           query(0) {}
    220 
    221     bool done;
    222     gfx::Size size;
    223     int bytes_per_row;
    224     int row_stride_bytes;
    225     unsigned char* pixels;
    226     base::Callback<void(bool)> callback;
    227     GLuint buffer;
    228     GLuint query;
    229   };
    230 
    231   // A readback pipeline that also converts the data to YUV before
    232   // reading it back.
    233   class ReadbackYUVImpl : public ReadbackYUVInterface {
    234    public:
    235     ReadbackYUVImpl(GLES2Interface* gl,
    236                     CopyTextureToImpl* copy_impl,
    237                     GLHelperScaling* scaler_impl,
    238                     GLHelper::ScalerQuality quality,
    239                     const gfx::Size& src_size,
    240                     const gfx::Rect& src_subrect,
    241                     const gfx::Size& dst_size,
    242                     const gfx::Rect& dst_subrect,
    243                     bool flip_vertically,
    244                     ReadbackSwizzle swizzle);
    245 
    246     virtual void ReadbackYUV(const gpu::Mailbox& mailbox,
    247                              uint32 sync_point,
    248                              const scoped_refptr<media::VideoFrame>& target,
    249                              const base::Callback<void(bool)>& callback)
    250         OVERRIDE;
    251 
    252     virtual ScalerInterface* scaler() OVERRIDE { return scaler_.scaler(); }
    253 
    254    private:
    255     GLES2Interface* gl_;
    256     CopyTextureToImpl* copy_impl_;
    257     gfx::Size dst_size_;
    258     gfx::Rect dst_subrect_;
    259     ReadbackSwizzle swizzle_;
    260     ScalerHolder scaler_;
    261     ScalerHolder y_;
    262     ScalerHolder u_;
    263     ScalerHolder v_;
    264 
    265     DISALLOW_COPY_AND_ASSIGN(ReadbackYUVImpl);
    266   };
    267 
    268   // A readback pipeline that also converts the data to YUV before
    269   // reading it back. This one uses Multiple Render Targets, which
    270   // may not be supported on all platforms.
    271   class ReadbackYUV_MRT : public ReadbackYUVInterface {
    272    public:
    273     ReadbackYUV_MRT(GLES2Interface* gl,
    274                     CopyTextureToImpl* copy_impl,
    275                     GLHelperScaling* scaler_impl,
    276                     GLHelper::ScalerQuality quality,
    277                     const gfx::Size& src_size,
    278                     const gfx::Rect& src_subrect,
    279                     const gfx::Size& dst_size,
    280                     const gfx::Rect& dst_subrect,
    281                     bool flip_vertically,
    282                     ReadbackSwizzle swizzle);
    283 
    284     virtual void ReadbackYUV(const gpu::Mailbox& mailbox,
    285                              uint32 sync_point,
    286                              const scoped_refptr<media::VideoFrame>& target,
    287                              const base::Callback<void(bool)>& callback)
    288         OVERRIDE;
    289 
    290     virtual ScalerInterface* scaler() OVERRIDE { return scaler_.scaler(); }
    291 
    292    private:
    293     GLES2Interface* gl_;
    294     CopyTextureToImpl* copy_impl_;
    295     gfx::Size dst_size_;
    296     gfx::Rect dst_subrect_;
    297     GLHelper::ScalerQuality quality_;
    298     ReadbackSwizzle swizzle_;
    299     ScalerHolder scaler_;
    300     scoped_ptr<content::GLHelperScaling::ShaderInterface> pass1_shader_;
    301     scoped_ptr<content::GLHelperScaling::ShaderInterface> pass2_shader_;
    302     TextureFrameBufferPair y_;
    303     ScopedTexture uv_;
    304     TextureFrameBufferPair u_;
    305     TextureFrameBufferPair v_;
    306 
    307     DISALLOW_COPY_AND_ASSIGN(ReadbackYUV_MRT);
    308   };
    309 
    310   // Copies the block of pixels specified with |src_subrect| from |src_texture|,
    311   // scales it to |dst_size|, writes it into a texture, and returns its ID.
    312   // |src_size| is the size of |src_texture|.
    313   GLuint ScaleTexture(GLuint src_texture,
    314                       const gfx::Size& src_size,
    315                       const gfx::Rect& src_subrect,
    316                       const gfx::Size& dst_size,
    317                       bool vertically_flip_texture,
    318                       bool swizzle,
    319                       SkBitmap::Config config,
    320                       GLHelper::ScalerQuality quality);
    321 
    322   static void nullcallback(bool success) {}
    323   void ReadbackDone(Request *request, int bytes_per_pixel);
    324   void FinishRequest(Request* request, bool result);
    325   void CancelRequests();
    326 
    327   static const float kRGBtoYColorWeights[];
    328   static const float kRGBtoUColorWeights[];
    329   static const float kRGBtoVColorWeights[];
    330 
    331   GLES2Interface* gl_;
    332   gpu::ContextSupport* context_support_;
    333   GLHelper* helper_;
    334 
    335   // A scoped flush that will ensure all resource deletions are flushed when
    336   // this object is destroyed. Must be declared before other Scoped* fields.
    337   ScopedFlush flush_;
    338 
    339   std::queue<Request*> request_queue_;
    340   GLint max_draw_buffers_;
    341 };
    342 
    343 GLHelper::ScalerInterface* GLHelper::CreateScaler(ScalerQuality quality,
    344                                                   const gfx::Size& src_size,
    345                                                   const gfx::Rect& src_subrect,
    346                                                   const gfx::Size& dst_size,
    347                                                   bool vertically_flip_texture,
    348                                                   bool swizzle) {
    349   InitScalerImpl();
    350   return scaler_impl_->CreateScaler(quality,
    351                                     src_size,
    352                                     src_subrect,
    353                                     dst_size,
    354                                     vertically_flip_texture,
    355                                     swizzle);
    356 }
    357 
    358 GLuint GLHelper::CopyTextureToImpl::ScaleTexture(
    359     GLuint src_texture,
    360     const gfx::Size& src_size,
    361     const gfx::Rect& src_subrect,
    362     const gfx::Size& dst_size,
    363     bool vertically_flip_texture,
    364     bool swizzle,
    365     SkBitmap::Config bitmap_config,
    366     GLHelper::ScalerQuality quality) {
    367   if (!IsReadbackConfigSupported(bitmap_config))
    368     return 0;
    369 
    370   scoped_ptr<ScalerInterface> scaler(
    371       helper_->CreateScaler(quality,
    372                             src_size,
    373                             src_subrect,
    374                             dst_size,
    375                             vertically_flip_texture,
    376                             swizzle));
    377   GLuint dst_texture = 0u;
    378   // Start with ARGB8888 params as any other format which is not
    379   // supported is already asserted above.
    380   GLenum format = GL_RGBA , type = GL_UNSIGNED_BYTE;
    381   gl_->GenTextures(1, &dst_texture);
    382   {
    383     ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
    384     switch (bitmap_config) {
    385       case SkBitmap::kARGB_8888_Config:
    386         // Do nothing params already set.
    387         break;
    388       case SkBitmap::kRGB_565_Config:
    389         format = GL_RGB;
    390         type = GL_UNSIGNED_SHORT_5_6_5;
    391         break;
    392       default:
    393         NOTREACHED();
    394         break;
    395     }
    396     gl_->TexImage2D(GL_TEXTURE_2D,
    397                     0,
    398                     format,
    399                     dst_size.width(),
    400                     dst_size.height(),
    401                     0,
    402                     format,
    403                     type,
    404                     NULL);
    405   }
    406   scaler->Scale(src_texture, dst_texture);
    407   return dst_texture;
    408 }
    409 
    410 void GLHelper::CopyTextureToImpl::ReadbackAsync(
    411     const gfx::Size& dst_size,
    412     int32 bytes_per_row,
    413     int32 row_stride_bytes,
    414     unsigned char* out,
    415     const SkBitmap::Config bitmap_config,
    416     ReadbackSwizzle swizzle,
    417     const base::Callback<void(bool)>& callback) {
    418   if (!IsReadbackConfigSupported(bitmap_config)) {
    419     callback.Run(false);
    420     return;
    421   }
    422   Request* request =
    423       new Request(dst_size, bytes_per_row, row_stride_bytes, out, callback);
    424   request_queue_.push(request);
    425   request->buffer = 0u;
    426   // Start with ARGB8888 params as any other format which is not
    427   // supported is already asserted above.
    428   GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
    429   int bytes_per_pixel = 4;
    430 
    431   switch (bitmap_config) {
    432     case SkBitmap::kARGB_8888_Config:
    433       if (swizzle == kSwizzleBGRA)
    434         format = GL_BGRA_EXT;
    435       break;
    436     case SkBitmap::kRGB_565_Config:
    437       format = GL_RGB;
    438       type = GL_UNSIGNED_SHORT_5_6_5;
    439       bytes_per_pixel = 2;
    440       break;
    441     default:
    442       NOTREACHED();
    443       break;
    444   }
    445   gl_->GenBuffers(1, &request->buffer);
    446   gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer);
    447   gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
    448                   bytes_per_pixel * dst_size.GetArea(),
    449                   NULL,
    450                   GL_STREAM_READ);
    451 
    452   request->query = 0u;
    453   gl_->GenQueriesEXT(1, &request->query);
    454   gl_->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, request->query);
    455   gl_->ReadPixels(0,
    456                   0,
    457                   dst_size.width(),
    458                   dst_size.height(),
    459                   format,
    460                   type,
    461                   NULL);
    462   gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM);
    463   gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
    464   context_support_->SignalQuery(
    465       request->query,
    466       base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(),
    467                  request, bytes_per_pixel));
    468 }
    469 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
    470     GLuint src_texture,
    471     const gfx::Size& src_size,
    472     const gfx::Rect& src_subrect,
    473     const gfx::Size& dst_size,
    474     unsigned char* out,
    475     const SkBitmap::Config bitmap_config,
    476     const base::Callback<void(bool)>& callback,
    477     GLHelper::ScalerQuality quality) {
    478   if (!IsReadbackConfigSupported(bitmap_config)) {
    479     callback.Run(false);
    480     return;
    481   }
    482   GLuint texture = ScaleTexture(src_texture,
    483                                 src_size,
    484                                 src_subrect,
    485                                 dst_size,
    486                                 true,
    487 #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
    488                                 true,
    489 #else
    490                                 false,
    491 #endif
    492                                 bitmap_config,
    493                                 quality);
    494   DCHECK(texture);
    495   ScopedFramebuffer dst_framebuffer(gl_);
    496   ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
    497                                                              dst_framebuffer);
    498   ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
    499   gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
    500                             GL_COLOR_ATTACHMENT0,
    501                             GL_TEXTURE_2D,
    502                             texture,
    503                             0);
    504   int bytes_per_pixel = 4;
    505   switch (bitmap_config) {
    506     case SkBitmap::kARGB_8888_Config:
    507       // Do nothing params already set.
    508       break;
    509     case SkBitmap::kRGB_565_Config:
    510       bytes_per_pixel = 2;
    511       break;
    512     default:
    513       NOTREACHED();
    514       break;
    515   }
    516   ReadbackAsync(dst_size,
    517                 dst_size.width() * bytes_per_pixel,
    518                 dst_size.width() * bytes_per_pixel,
    519                 out,
    520                 bitmap_config,
    521                 kSwizzleNone,
    522                 callback);
    523   gl_->DeleteTextures(1, &texture);
    524 }
    525 
    526 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(
    527     GLuint texture,
    528     const gfx::Rect& src_rect,
    529     unsigned char* out,
    530     SkBitmap::Config bitmap_config) {
    531   if (!IsReadbackConfigSupported(bitmap_config))
    532     return;
    533 
    534   ScopedFramebuffer dst_framebuffer(gl_);
    535   ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
    536                                                              dst_framebuffer);
    537   ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
    538   gl_->FramebufferTexture2D(
    539       GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
    540   GLenum format =
    541       (bitmap_config == SkBitmap::kRGB_565_Config) ? GL_RGB : GL_RGBA;
    542   GLenum type = (bitmap_config == SkBitmap::kRGB_565_Config)
    543                     ? GL_UNSIGNED_SHORT_5_6_5
    544                     : GL_UNSIGNED_BYTE;
    545   gl_->ReadPixels(src_rect.x(),
    546                   src_rect.y(),
    547                   src_rect.width(),
    548                   src_rect.height(),
    549                   format,
    550                   type,
    551                   out);
    552 }
    553 
    554 void GLHelper::CopyTextureToImpl::ReadbackTextureAsync(
    555     GLuint texture,
    556     const gfx::Size& dst_size,
    557     unsigned char* out,
    558     SkBitmap::Config bitmap_config,
    559     const base::Callback<void(bool)>& callback) {
    560   if (!IsReadbackConfigSupported(bitmap_config))
    561     return;
    562 
    563   ScopedFramebuffer dst_framebuffer(gl_);
    564   ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
    565                                                              dst_framebuffer);
    566   ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
    567   gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
    568                             GL_COLOR_ATTACHMENT0,
    569                             GL_TEXTURE_2D,
    570                             texture,
    571                             0);
    572   int bytes_per_pixel = (bitmap_config == SkBitmap::kRGB_565_Config) ? 2 : 4;
    573   ReadbackAsync(dst_size,
    574                 dst_size.width() * bytes_per_pixel,
    575                 dst_size.width() * bytes_per_pixel,
    576                 out,
    577                 bitmap_config,
    578                 kSwizzleNone,
    579                 callback);
    580 }
    581 
    582 GLuint GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
    583     GLuint src_texture,
    584     const gfx::Size& src_size,
    585     const gfx::Size& dst_size,
    586     bool vertically_flip_texture,
    587     GLHelper::ScalerQuality quality) {
    588   return ScaleTexture(src_texture,
    589                       src_size,
    590                       gfx::Rect(src_size),
    591                       dst_size,
    592                       vertically_flip_texture,
    593                       false,
    594                       SkBitmap::kARGB_8888_Config,
    595                       quality);
    596 }
    597 
    598 bool GLHelper::CopyTextureToImpl::IsReadbackConfigSupported(
    599     SkBitmap::Config bitmap_config) {
    600   if (!helper_) {
    601     DCHECK(helper_);
    602     return false;
    603   }
    604   return helper_->IsReadbackConfigSupported(bitmap_config);
    605 }
    606 
    607 void GLHelper::CopyTextureToImpl::ReadbackDone(Request* finished_request,
    608                                                int bytes_per_pixel) {
    609   TRACE_EVENT0("mirror",
    610                "GLHelper::CopyTextureToImpl::CheckReadbackFramebufferComplete");
    611   finished_request->done = true;
    612 
    613   // We process transfer requests in the order they were received, regardless
    614   // of the order we get the callbacks in.
    615   while (!request_queue_.empty()) {
    616     Request* request = request_queue_.front();
    617     if (!request->done) {
    618       break;
    619     }
    620 
    621     bool result = false;
    622     if (request->buffer != 0) {
    623       gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer);
    624       unsigned char* data = static_cast<unsigned char*>(gl_->MapBufferCHROMIUM(
    625           GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY));
    626       if (data) {
    627         result = true;
    628         if (request->bytes_per_row == request->size.width() * bytes_per_pixel &&
    629             request->bytes_per_row == request->row_stride_bytes) {
    630           memcpy(request->pixels, data,
    631                  request->size.GetArea() * bytes_per_pixel);
    632         } else {
    633           unsigned char* out = request->pixels;
    634           for (int y = 0; y < request->size.height(); y++) {
    635             memcpy(out, data, request->bytes_per_row);
    636             out += request->row_stride_bytes;
    637             data += request->size.width() * bytes_per_pixel;
    638           }
    639         }
    640         gl_->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM);
    641       }
    642       gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
    643     }
    644     FinishRequest(request, result);
    645   }
    646 }
    647 
    648 void GLHelper::CopyTextureToImpl::FinishRequest(Request* request, bool result) {
    649   TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::FinishRequest");
    650   DCHECK(request_queue_.front() == request);
    651   request_queue_.pop();
    652   request->callback.Run(result);
    653   ScopedFlush flush(gl_);
    654   if (request->query != 0) {
    655     gl_->DeleteQueriesEXT(1, &request->query);
    656     request->query = 0;
    657   }
    658   if (request->buffer != 0) {
    659     gl_->DeleteBuffers(1, &request->buffer);
    660     request->buffer = 0;
    661   }
    662   delete request;
    663 }
    664 
    665 void GLHelper::CopyTextureToImpl::CancelRequests() {
    666   while (!request_queue_.empty()) {
    667     Request* request = request_queue_.front();
    668     FinishRequest(request, false);
    669   }
    670 }
    671 
    672 GLHelper::GLHelper(GLES2Interface* gl, gpu::ContextSupport* context_support)
    673     : gl_(gl),
    674       context_support_(context_support),
    675       readback_support_(new GLHelperReadbackSupport(gl)) {}
    676 
    677 GLHelper::~GLHelper() {}
    678 
    679 void GLHelper::CropScaleReadbackAndCleanTexture(
    680     GLuint src_texture,
    681     const gfx::Size& src_size,
    682     const gfx::Rect& src_subrect,
    683     const gfx::Size& dst_size,
    684     unsigned char* out,
    685     const SkBitmap::Config config,
    686     const base::Callback<void(bool)>& callback,
    687     GLHelper::ScalerQuality quality) {
    688   InitCopyTextToImpl();
    689   copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(
    690       src_texture,
    691       src_size,
    692       src_subrect,
    693       dst_size,
    694       out,
    695       config,
    696       callback,
    697       quality);
    698 }
    699 
    700 void GLHelper::CropScaleReadbackAndCleanMailbox(
    701     const gpu::Mailbox& src_mailbox,
    702     uint32 sync_point,
    703     const gfx::Size& src_size,
    704     const gfx::Rect& src_subrect,
    705     const gfx::Size& dst_size,
    706     unsigned char* out,
    707     const SkBitmap::Config bitmap_config,
    708     const base::Callback<void(bool)>& callback,
    709     GLHelper::ScalerQuality quality) {
    710   GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point);
    711   CropScaleReadbackAndCleanTexture(
    712       mailbox_texture, src_size, src_subrect, dst_size, out,
    713       bitmap_config,
    714       callback,
    715       quality);
    716   gl_->DeleteTextures(1, &mailbox_texture);
    717 }
    718 
    719 void GLHelper::ReadbackTextureSync(GLuint texture,
    720                                    const gfx::Rect& src_rect,
    721                                    unsigned char* out,
    722                                    SkBitmap::Config format) {
    723   InitCopyTextToImpl();
    724   copy_texture_to_impl_->ReadbackTextureSync(texture, src_rect, out, format);
    725 }
    726 
    727 void GLHelper::ReadbackTextureAsync(
    728     GLuint texture,
    729     const gfx::Size& dst_size,
    730     unsigned char* out,
    731     SkBitmap::Config config,
    732     const base::Callback<void(bool)>& callback) {
    733   InitCopyTextToImpl();
    734   copy_texture_to_impl_->ReadbackTextureAsync(texture,
    735                                               dst_size,
    736                                               out,
    737                                               config,
    738                                               callback);
    739 }
    740 
    741 GLuint GLHelper::CopyTexture(GLuint texture, const gfx::Size& size) {
    742   InitCopyTextToImpl();
    743   return copy_texture_to_impl_->CopyAndScaleTexture(
    744       texture, size, size, false, GLHelper::SCALER_QUALITY_FAST);
    745 }
    746 
    747 GLuint GLHelper::CopyAndScaleTexture(GLuint texture,
    748                                      const gfx::Size& src_size,
    749                                      const gfx::Size& dst_size,
    750                                      bool vertically_flip_texture,
    751                                      ScalerQuality quality) {
    752   InitCopyTextToImpl();
    753   return copy_texture_to_impl_->CopyAndScaleTexture(
    754       texture, src_size, dst_size, vertically_flip_texture, quality);
    755 }
    756 
    757 GLuint GLHelper::CompileShaderFromSource(const GLchar* source, GLenum type) {
    758   GLuint shader = gl_->CreateShader(type);
    759   GLint length = strlen(source);
    760   gl_->ShaderSource(shader, 1, &source, &length);
    761   gl_->CompileShader(shader);
    762   GLint compile_status = 0;
    763   gl_->GetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
    764   if (!compile_status) {
    765     GLint log_length = 0;
    766     gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
    767     if (log_length) {
    768       scoped_ptr<GLchar[]> log(new GLchar[log_length]);
    769       GLsizei returned_log_length = 0;
    770       gl_->GetShaderInfoLog(
    771           shader, log_length, &returned_log_length, log.get());
    772       LOG(ERROR) << std::string(log.get(), returned_log_length);
    773     }
    774     gl_->DeleteShader(shader);
    775     return 0;
    776   }
    777   return shader;
    778 }
    779 
    780 void GLHelper::InitCopyTextToImpl() {
    781   // Lazily initialize |copy_texture_to_impl_|
    782   if (!copy_texture_to_impl_)
    783     copy_texture_to_impl_.reset(
    784         new CopyTextureToImpl(gl_, context_support_, this));
    785 }
    786 
    787 void GLHelper::InitScalerImpl() {
    788   // Lazily initialize |scaler_impl_|
    789   if (!scaler_impl_)
    790     scaler_impl_.reset(new GLHelperScaling(gl_, this));
    791 }
    792 
    793 GLint GLHelper::MaxDrawBuffers() {
    794   InitCopyTextToImpl();
    795   return copy_texture_to_impl_->MaxDrawBuffers();
    796 }
    797 
    798 void GLHelper::CopySubBufferDamage(GLuint texture,
    799                                    GLuint previous_texture,
    800                                    const SkRegion& new_damage,
    801                                    const SkRegion& old_damage) {
    802   SkRegion region(old_damage);
    803   if (region.op(new_damage, SkRegion::kDifference_Op)) {
    804     ScopedFramebuffer dst_framebuffer(gl_);
    805     ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
    806                                                                dst_framebuffer);
    807     ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
    808     gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
    809                               GL_COLOR_ATTACHMENT0,
    810                               GL_TEXTURE_2D,
    811                               previous_texture,
    812                               0);
    813     for (SkRegion::Iterator it(region); !it.done(); it.next()) {
    814       const SkIRect& rect = it.rect();
    815       gl_->CopyTexSubImage2D(GL_TEXTURE_2D,
    816                              0,
    817                              rect.x(),
    818                              rect.y(),
    819                              rect.x(),
    820                              rect.y(),
    821                              rect.width(),
    822                              rect.height());
    823     }
    824     gl_->Flush();
    825   }
    826 }
    827 
    828 GLuint GLHelper::CreateTexture() {
    829   GLuint texture = 0u;
    830   gl_->GenTextures(1, &texture);
    831   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
    832   gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    833   gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    834   gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    835   gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    836   return texture;
    837 }
    838 
    839 void GLHelper::DeleteTexture(GLuint texture_id) {
    840   gl_->DeleteTextures(1, &texture_id);
    841 }
    842 
    843 uint32 GLHelper::InsertSyncPoint() { return gl_->InsertSyncPointCHROMIUM(); }
    844 
    845 void GLHelper::WaitSyncPoint(uint32 sync_point) {
    846   gl_->WaitSyncPointCHROMIUM(sync_point);
    847 }
    848 
    849 gpu::MailboxHolder GLHelper::ProduceMailboxHolderFromTexture(
    850     GLuint texture_id) {
    851   gpu::Mailbox mailbox;
    852   gl_->GenMailboxCHROMIUM(mailbox.name);
    853   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture_id);
    854   gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
    855   return gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, InsertSyncPoint());
    856 }
    857 
    858 GLuint GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
    859                                          uint32 sync_point) {
    860   if (mailbox.IsZero())
    861     return 0;
    862   if (sync_point)
    863     WaitSyncPoint(sync_point);
    864   GLuint texture = CreateTexture();
    865   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
    866   gl_->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
    867   return texture;
    868 }
    869 
    870 void GLHelper::ResizeTexture(GLuint texture, const gfx::Size& size) {
    871   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
    872   gl_->TexImage2D(GL_TEXTURE_2D,
    873                   0,
    874                   GL_RGB,
    875                   size.width(),
    876                   size.height(),
    877                   0,
    878                   GL_RGB,
    879                   GL_UNSIGNED_BYTE,
    880                   NULL);
    881 }
    882 
    883 void GLHelper::CopyTextureSubImage(GLuint texture, const gfx::Rect& rect) {
    884   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
    885   gl_->CopyTexSubImage2D(GL_TEXTURE_2D,
    886                          0,
    887                          rect.x(),
    888                          rect.y(),
    889                          rect.x(),
    890                          rect.y(),
    891                          rect.width(),
    892                          rect.height());
    893 }
    894 
    895 void GLHelper::CopyTextureFullImage(GLuint texture, const gfx::Size& size) {
    896   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
    897   gl_->CopyTexImage2D(
    898       GL_TEXTURE_2D, 0, GL_RGB, 0, 0, size.width(), size.height(), 0);
    899 }
    900 
    901 void GLHelper::Flush() {
    902   gl_->Flush();
    903 }
    904 
    905 void GLHelper::CopyTextureToImpl::ReadbackPlane(
    906     TextureFrameBufferPair* source,
    907     const scoped_refptr<media::VideoFrame>& target,
    908     int plane,
    909     int size_shift,
    910     const gfx::Rect& dst_subrect,
    911     ReadbackSwizzle swizzle,
    912     const base::Callback<void(bool)>& callback) {
    913   gl_->BindFramebuffer(GL_FRAMEBUFFER, source->framebuffer());
    914   size_t offset = target->stride(plane) * (dst_subrect.y() >> size_shift) +
    915       (dst_subrect.x() >> size_shift);
    916   ReadbackAsync(source->size(),
    917                 dst_subrect.width() >> size_shift,
    918                 target->stride(plane),
    919                 target->data(plane) + offset,
    920                 SkBitmap::kARGB_8888_Config,
    921                 swizzle,
    922                 callback);
    923 }
    924 
    925 const float GLHelper::CopyTextureToImpl::kRGBtoYColorWeights[] = {
    926     0.257f, 0.504f, 0.098f, 0.0625f};
    927 const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = {
    928     -0.148f, -0.291f, 0.439f, 0.5f};
    929 const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = {
    930     0.439f, -0.368f, -0.071f, 0.5f};
    931 
    932 // YUV readback constructors. Initiates the main scaler pipeline and
    933 // one planar scaler for each of the Y, U and V planes.
    934 GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
    935     GLES2Interface* gl,
    936     CopyTextureToImpl* copy_impl,
    937     GLHelperScaling* scaler_impl,
    938     GLHelper::ScalerQuality quality,
    939     const gfx::Size& src_size,
    940     const gfx::Rect& src_subrect,
    941     const gfx::Size& dst_size,
    942     const gfx::Rect& dst_subrect,
    943     bool flip_vertically,
    944     ReadbackSwizzle swizzle)
    945     : gl_(gl),
    946       copy_impl_(copy_impl),
    947       dst_size_(dst_size),
    948       dst_subrect_(dst_subrect),
    949       swizzle_(swizzle),
    950       scaler_(gl,
    951               scaler_impl->CreateScaler(quality,
    952                                         src_size,
    953                                         src_subrect,
    954                                         dst_subrect.size(),
    955                                         flip_vertically,
    956                                         false)),
    957       y_(gl,
    958          scaler_impl->CreatePlanarScaler(
    959              dst_subrect.size(),
    960              gfx::Rect(0,
    961                        0,
    962                        (dst_subrect.width() + 3) & ~3,
    963                        dst_subrect.height()),
    964              gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
    965              false,
    966              (swizzle == kSwizzleBGRA),
    967              kRGBtoYColorWeights)),
    968       u_(gl,
    969          scaler_impl->CreatePlanarScaler(
    970              dst_subrect.size(),
    971              gfx::Rect(0,
    972                        0,
    973                        (dst_subrect.width() + 7) & ~7,
    974                        (dst_subrect.height() + 1) & ~1),
    975              gfx::Size((dst_subrect.width() + 7) / 8,
    976                        (dst_subrect.height() + 1) / 2),
    977              false,
    978              (swizzle == kSwizzleBGRA),
    979              kRGBtoUColorWeights)),
    980       v_(gl,
    981          scaler_impl->CreatePlanarScaler(
    982              dst_subrect.size(),
    983              gfx::Rect(0,
    984                        0,
    985                        (dst_subrect.width() + 7) & ~7,
    986                        (dst_subrect.height() + 1) & ~1),
    987              gfx::Size((dst_subrect.width() + 7) / 8,
    988                        (dst_subrect.height() + 1) / 2),
    989              false,
    990              (swizzle == kSwizzleBGRA),
    991              kRGBtoVColorWeights)) {
    992   DCHECK(!(dst_size.width() & 1));
    993   DCHECK(!(dst_size.height() & 1));
    994   DCHECK(!(dst_subrect.width() & 1));
    995   DCHECK(!(dst_subrect.height() & 1));
    996   DCHECK(!(dst_subrect.x() & 1));
    997   DCHECK(!(dst_subrect.y() & 1));
    998 }
    999 
   1000 static void CallbackKeepingVideoFrameAlive(
   1001     scoped_refptr<media::VideoFrame> video_frame,
   1002     const base::Callback<void(bool)>& callback,
   1003     bool success) {
   1004   callback.Run(success);
   1005 }
   1006 
   1007 void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV(
   1008     const gpu::Mailbox& mailbox,
   1009     uint32 sync_point,
   1010     const scoped_refptr<media::VideoFrame>& target,
   1011     const base::Callback<void(bool)>& callback) {
   1012   GLuint mailbox_texture =
   1013       copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point);
   1014 
   1015   // Scale texture to right size.
   1016   scaler_.Scale(mailbox_texture);
   1017   gl_->DeleteTextures(1, &mailbox_texture);
   1018 
   1019   // Convert the scaled texture in to Y, U and V planes.
   1020   y_.Scale(scaler_.texture());
   1021   u_.Scale(scaler_.texture());
   1022   v_.Scale(scaler_.texture());
   1023 
   1024   if (target->coded_size() != dst_size_) {
   1025     DCHECK(target->coded_size() == dst_size_);
   1026     LOG(ERROR) << "ReadbackYUV size error!";
   1027     callback.Run(false);
   1028     return;
   1029   }
   1030 
   1031   // Read back planes, one at a time. Keep the video frame alive while doing the
   1032   // readback.
   1033   copy_impl_->ReadbackPlane(y_.texture_and_framebuffer(),
   1034                             target,
   1035                             media::VideoFrame::kYPlane,
   1036                             0,
   1037                             dst_subrect_,
   1038                             swizzle_,
   1039                             base::Bind(&nullcallback));
   1040   copy_impl_->ReadbackPlane(u_.texture_and_framebuffer(),
   1041                             target,
   1042                             media::VideoFrame::kUPlane,
   1043                             1,
   1044                             dst_subrect_,
   1045                             swizzle_,
   1046                             base::Bind(&nullcallback));
   1047   copy_impl_->ReadbackPlane(
   1048       v_.texture_and_framebuffer(),
   1049       target,
   1050       media::VideoFrame::kVPlane,
   1051       1,
   1052       dst_subrect_,
   1053       swizzle_,
   1054       base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
   1055   gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
   1056   media::LetterboxYUV(target, dst_subrect_);
   1057 }
   1058 
   1059 // YUV readback constructors. Initiates the main scaler pipeline and
   1060 // one planar scaler for each of the Y, U and V planes.
   1061 GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT(
   1062     GLES2Interface* gl,
   1063     CopyTextureToImpl* copy_impl,
   1064     GLHelperScaling* scaler_impl,
   1065     GLHelper::ScalerQuality quality,
   1066     const gfx::Size& src_size,
   1067     const gfx::Rect& src_subrect,
   1068     const gfx::Size& dst_size,
   1069     const gfx::Rect& dst_subrect,
   1070     bool flip_vertically,
   1071     ReadbackSwizzle swizzle)
   1072     : gl_(gl),
   1073       copy_impl_(copy_impl),
   1074       dst_size_(dst_size),
   1075       dst_subrect_(dst_subrect),
   1076       quality_(quality),
   1077       swizzle_(swizzle),
   1078       scaler_(gl,
   1079               scaler_impl->CreateScaler(quality,
   1080                                         src_size,
   1081                                         src_subrect,
   1082                                         dst_subrect.size(),
   1083                                         false,
   1084                                         false)),
   1085       pass1_shader_(scaler_impl->CreateYuvMrtShader(
   1086           dst_subrect.size(),
   1087           gfx::Rect(0, 0, (dst_subrect.width() + 3) & ~3, dst_subrect.height()),
   1088           gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
   1089           flip_vertically,
   1090           (swizzle == kSwizzleBGRA),
   1091           GLHelperScaling::SHADER_YUV_MRT_PASS1)),
   1092       pass2_shader_(scaler_impl->CreateYuvMrtShader(
   1093           gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
   1094           gfx::Rect(0,
   1095                     0,
   1096                     (dst_subrect.width() + 7) / 8 * 2,
   1097                     dst_subrect.height()),
   1098           gfx::Size((dst_subrect.width() + 7) / 8,
   1099                     (dst_subrect.height() + 1) / 2),
   1100           false,
   1101           (swizzle == kSwizzleBGRA),
   1102           GLHelperScaling::SHADER_YUV_MRT_PASS2)),
   1103       y_(gl, gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height())),
   1104       uv_(gl),
   1105       u_(gl,
   1106          gfx::Size((dst_subrect.width() + 7) / 8,
   1107                    (dst_subrect.height() + 1) / 2)),
   1108       v_(gl,
   1109          gfx::Size((dst_subrect.width() + 7) / 8,
   1110                    (dst_subrect.height() + 1) / 2)) {
   1111 
   1112   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl, uv_);
   1113   gl->TexImage2D(GL_TEXTURE_2D,
   1114                  0,
   1115                  GL_RGBA,
   1116                  (dst_subrect.width() + 3) / 4,
   1117                  dst_subrect.height(),
   1118                  0,
   1119                  GL_RGBA,
   1120                  GL_UNSIGNED_BYTE,
   1121                  NULL);
   1122 
   1123   DCHECK(!(dst_size.width() & 1));
   1124   DCHECK(!(dst_size.height() & 1));
   1125   DCHECK(!(dst_subrect.width() & 1));
   1126   DCHECK(!(dst_subrect.height() & 1));
   1127   DCHECK(!(dst_subrect.x() & 1));
   1128   DCHECK(!(dst_subrect.y() & 1));
   1129 }
   1130 
   1131 void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV(
   1132     const gpu::Mailbox& mailbox,
   1133     uint32 sync_point,
   1134     const scoped_refptr<media::VideoFrame>& target,
   1135     const base::Callback<void(bool)>& callback) {
   1136   GLuint mailbox_texture =
   1137       copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point);
   1138 
   1139   GLuint texture;
   1140   if (quality_ == GLHelper::SCALER_QUALITY_FAST) {
   1141     // Optimization: SCALER_QUALITY_FAST is just a single bilinear
   1142     // pass, which pass1_shader_ can do just as well, so let's skip
   1143     // the actual scaling in that case.
   1144     texture = mailbox_texture;
   1145   } else {
   1146     // Scale texture to right size.
   1147     scaler_.Scale(mailbox_texture);
   1148     texture = scaler_.texture();
   1149   }
   1150 
   1151   std::vector<GLuint> outputs(2);
   1152   // Convert the scaled texture in to Y, U and V planes.
   1153   outputs[0] = y_.texture();
   1154   outputs[1] = uv_;
   1155   pass1_shader_->Execute(texture, outputs);
   1156 
   1157   gl_->DeleteTextures(1, &mailbox_texture);
   1158 
   1159   outputs[0] = u_.texture();
   1160   outputs[1] = v_.texture();
   1161   pass2_shader_->Execute(uv_, outputs);
   1162 
   1163   if (target->coded_size() != dst_size_) {
   1164     DCHECK(target->coded_size() == dst_size_);
   1165     LOG(ERROR) << "ReadbackYUV size error!";
   1166     callback.Run(false);
   1167     return;
   1168   }
   1169 
   1170   // Read back planes, one at a time.
   1171   copy_impl_->ReadbackPlane(&y_,
   1172                             target,
   1173                             media::VideoFrame::kYPlane,
   1174                             0,
   1175                             dst_subrect_,
   1176                             swizzle_,
   1177                             base::Bind(&nullcallback));
   1178   copy_impl_->ReadbackPlane(&u_,
   1179                             target,
   1180                             media::VideoFrame::kUPlane,
   1181                             1,
   1182                             dst_subrect_,
   1183                             swizzle_,
   1184                             base::Bind(&nullcallback));
   1185   copy_impl_->ReadbackPlane(
   1186       &v_,
   1187       target,
   1188       media::VideoFrame::kVPlane,
   1189       1,
   1190       dst_subrect_,
   1191       swizzle_,
   1192       base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
   1193   gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
   1194   media::LetterboxYUV(target, dst_subrect_);
   1195 }
   1196 
   1197 bool GLHelper::IsReadbackConfigSupported(SkBitmap::Config texture_format) {
   1198   DCHECK(readback_support_.get());
   1199   return readback_support_.get()->IsReadbackConfigSupported(texture_format);
   1200 }
   1201 
   1202 ReadbackYUVInterface* GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
   1203     GLHelper::ScalerQuality quality,
   1204     const gfx::Size& src_size,
   1205     const gfx::Rect& src_subrect,
   1206     const gfx::Size& dst_size,
   1207     const gfx::Rect& dst_subrect,
   1208     bool flip_vertically,
   1209     bool use_mrt) {
   1210   helper_->InitScalerImpl();
   1211   // Query preferred format for glReadPixels, if is is GL_BGRA then use that
   1212   // and trigger the appropriate swizzle in the YUV shaders.
   1213   GLint format = 0, type = 0;
   1214   ReadbackSwizzle swizzle = kSwizzleNone;
   1215   helper_->readback_support_.get()->GetAdditionalFormat(GL_RGBA,
   1216                                                         GL_UNSIGNED_BYTE,
   1217                                                         &format, &type);
   1218   if (format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE)
   1219     swizzle = kSwizzleBGRA;
   1220   if (max_draw_buffers_ >= 2 && use_mrt) {
   1221     return new ReadbackYUV_MRT(gl_,
   1222                                this,
   1223                                helper_->scaler_impl_.get(),
   1224                                quality,
   1225                                src_size,
   1226                                src_subrect,
   1227                                dst_size,
   1228                                dst_subrect,
   1229                                flip_vertically,
   1230                                swizzle);
   1231   }
   1232   return new ReadbackYUVImpl(gl_,
   1233                              this,
   1234                              helper_->scaler_impl_.get(),
   1235                              quality,
   1236                              src_size,
   1237                              src_subrect,
   1238                              dst_size,
   1239                              dst_subrect,
   1240                              flip_vertically,
   1241                              swizzle);
   1242 }
   1243 
   1244 ReadbackYUVInterface* GLHelper::CreateReadbackPipelineYUV(
   1245     ScalerQuality quality,
   1246     const gfx::Size& src_size,
   1247     const gfx::Rect& src_subrect,
   1248     const gfx::Size& dst_size,
   1249     const gfx::Rect& dst_subrect,
   1250     bool flip_vertically,
   1251     bool use_mrt) {
   1252   InitCopyTextToImpl();
   1253   return copy_texture_to_impl_->CreateReadbackPipelineYUV(quality,
   1254                                                           src_size,
   1255                                                           src_subrect,
   1256                                                           dst_size,
   1257                                                           dst_subrect,
   1258                                                           flip_vertically,
   1259                                                           use_mrt);
   1260 }
   1261 
   1262 }  // namespace content
   1263