Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / client / gl_helper.cc
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 typedef GLHelperReadbackSupport::FormatSupport FormatSupport;
109
110 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates
111 // the data needed for it.
112 class GLHelper::CopyTextureToImpl
113     : public base::SupportsWeakPtr<GLHelper::CopyTextureToImpl> {
114  public:
115   CopyTextureToImpl(GLES2Interface* gl,
116                     gpu::ContextSupport* context_support,
117                     GLHelper* helper)
118       : gl_(gl),
119         context_support_(context_support),
120         helper_(helper),
121         flush_(gl),
122         max_draw_buffers_(0) {
123     const GLubyte* extensions = gl_->GetString(GL_EXTENSIONS);
124     if (!extensions)
125       return;
126     std::string extensions_string =
127         " " + std::string(reinterpret_cast<const char*>(extensions)) + " ";
128     if (extensions_string.find(" GL_EXT_draw_buffers ") != std::string::npos) {
129       gl_->GetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &max_draw_buffers_);
130     }
131   }
132   ~CopyTextureToImpl() { CancelRequests(); }
133
134   GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
135                                  uint32 sync_point) {
136     return helper_->ConsumeMailboxToTexture(mailbox, sync_point);
137   }
138
139   void CropScaleReadbackAndCleanTexture(
140       GLuint src_texture,
141       const gfx::Size& src_size,
142       const gfx::Rect& src_subrect,
143       const gfx::Size& dst_size,
144       unsigned char* out,
145       const SkColorType out_color_type,
146       const base::Callback<void(bool)>& callback,
147       GLHelper::ScalerQuality quality);
148
149   void ReadbackTextureSync(GLuint texture,
150                            const gfx::Rect& src_rect,
151                            unsigned char* out,
152                            SkColorType format);
153
154   void ReadbackTextureAsync(GLuint texture,
155                             const gfx::Size& dst_size,
156                             unsigned char* out,
157                             SkColorType color_type,
158                             const base::Callback<void(bool)>& callback);
159
160   // Reads back bytes from the currently bound frame buffer.
161   // Note that dst_size is specified in bytes, not pixels.
162   void ReadbackAsync(const gfx::Size& dst_size,
163                      int32 bytes_per_row,     // generally dst_size.width() * 4
164                      int32 row_stride_bytes,  // generally dst_size.width() * 4
165                      unsigned char* out,
166                      GLenum format,
167                      GLenum type,
168                      size_t bytes_per_pixel,
169                      const base::Callback<void(bool)>& callback);
170
171   void ReadbackPlane(TextureFrameBufferPair* source,
172                      const scoped_refptr<media::VideoFrame>& target,
173                      int plane,
174                      int size_shift,
175                      const gfx::Rect& dst_subrect,
176                      ReadbackSwizzle swizzle,
177                      const base::Callback<void(bool)>& callback);
178
179   GLuint CopyAndScaleTexture(GLuint texture,
180                              const gfx::Size& src_size,
181                              const gfx::Size& dst_size,
182                              bool vertically_flip_texture,
183                              GLHelper::ScalerQuality quality);
184
185   ReadbackYUVInterface* CreateReadbackPipelineYUV(
186       GLHelper::ScalerQuality quality,
187       const gfx::Size& src_size,
188       const gfx::Rect& src_subrect,
189       const gfx::Size& dst_size,
190       const gfx::Rect& dst_subrect,
191       bool flip_vertically,
192       bool use_mrt);
193
194   // Returns the maximum number of draw buffers available,
195   // 0 if GL_EXT_draw_buffers is not available.
196   GLint MaxDrawBuffers() const { return max_draw_buffers_; }
197
198   FormatSupport GetReadbackConfig(SkColorType color_type,
199                                   bool can_swizzle,
200                                   GLenum* format,
201                                   GLenum* type,
202                                   size_t* bytes_per_pixel);
203
204  private:
205   // A single request to CropScaleReadbackAndCleanTexture.
206   // The main thread can cancel the request, before it's handled by the helper
207   // thread, by resetting the texture and pixels fields. Alternatively, the
208   // thread marks that it handles the request by resetting the pixels field
209   // (meaning it guarantees that the callback with be called).
210   // In either case, the callback must be called exactly once, and the texture
211   // must be deleted by the main thread gl.
212   struct Request {
213     Request(const gfx::Size& size_,
214             int32 bytes_per_row_,
215             int32 row_stride_bytes_,
216             unsigned char* pixels_,
217             const base::Callback<void(bool)>& callback_)
218         : done(false),
219           size(size_),
220           bytes_per_row(bytes_per_row_),
221           row_stride_bytes(row_stride_bytes_),
222           pixels(pixels_),
223           callback(callback_),
224           buffer(0),
225           query(0) {}
226
227     bool done;
228     gfx::Size size;
229     int bytes_per_row;
230     int row_stride_bytes;
231     unsigned char* pixels;
232     base::Callback<void(bool)> callback;
233     GLuint buffer;
234     GLuint query;
235   };
236
237   // A readback pipeline that also converts the data to YUV before
238   // reading it back.
239   class ReadbackYUVImpl : public ReadbackYUVInterface {
240    public:
241     ReadbackYUVImpl(GLES2Interface* gl,
242                     CopyTextureToImpl* copy_impl,
243                     GLHelperScaling* scaler_impl,
244                     GLHelper::ScalerQuality quality,
245                     const gfx::Size& src_size,
246                     const gfx::Rect& src_subrect,
247                     const gfx::Size& dst_size,
248                     const gfx::Rect& dst_subrect,
249                     bool flip_vertically,
250                     ReadbackSwizzle swizzle);
251
252     void ReadbackYUV(const gpu::Mailbox& mailbox,
253                      uint32 sync_point,
254                      const scoped_refptr<media::VideoFrame>& target,
255                      const base::Callback<void(bool)>& callback) override;
256
257     ScalerInterface* scaler() override { return scaler_.scaler(); }
258
259    private:
260     GLES2Interface* gl_;
261     CopyTextureToImpl* copy_impl_;
262     gfx::Size dst_size_;
263     gfx::Rect dst_subrect_;
264     ReadbackSwizzle swizzle_;
265     ScalerHolder scaler_;
266     ScalerHolder y_;
267     ScalerHolder u_;
268     ScalerHolder v_;
269
270     DISALLOW_COPY_AND_ASSIGN(ReadbackYUVImpl);
271   };
272
273   // A readback pipeline that also converts the data to YUV before
274   // reading it back. This one uses Multiple Render Targets, which
275   // may not be supported on all platforms.
276   class ReadbackYUV_MRT : public ReadbackYUVInterface {
277    public:
278     ReadbackYUV_MRT(GLES2Interface* gl,
279                     CopyTextureToImpl* copy_impl,
280                     GLHelperScaling* scaler_impl,
281                     GLHelper::ScalerQuality quality,
282                     const gfx::Size& src_size,
283                     const gfx::Rect& src_subrect,
284                     const gfx::Size& dst_size,
285                     const gfx::Rect& dst_subrect,
286                     bool flip_vertically,
287                     ReadbackSwizzle swizzle);
288
289     void ReadbackYUV(const gpu::Mailbox& mailbox,
290                      uint32 sync_point,
291                      const scoped_refptr<media::VideoFrame>& target,
292                      const base::Callback<void(bool)>& callback) override;
293
294     ScalerInterface* scaler() override { return scaler_.scaler(); }
295
296    private:
297     GLES2Interface* gl_;
298     CopyTextureToImpl* copy_impl_;
299     gfx::Size dst_size_;
300     gfx::Rect dst_subrect_;
301     GLHelper::ScalerQuality quality_;
302     ReadbackSwizzle swizzle_;
303     ScalerHolder scaler_;
304     scoped_ptr<content::GLHelperScaling::ShaderInterface> pass1_shader_;
305     scoped_ptr<content::GLHelperScaling::ShaderInterface> pass2_shader_;
306     TextureFrameBufferPair y_;
307     ScopedTexture uv_;
308     TextureFrameBufferPair u_;
309     TextureFrameBufferPair v_;
310
311     DISALLOW_COPY_AND_ASSIGN(ReadbackYUV_MRT);
312   };
313
314   // Copies the block of pixels specified with |src_subrect| from |src_texture|,
315   // scales it to |dst_size|, writes it into a texture, and returns its ID.
316   // |src_size| is the size of |src_texture|.
317   GLuint ScaleTexture(GLuint src_texture,
318                       const gfx::Size& src_size,
319                       const gfx::Rect& src_subrect,
320                       const gfx::Size& dst_size,
321                       bool vertically_flip_texture,
322                       bool swizzle,
323                       SkColorType color_type,
324                       GLHelper::ScalerQuality quality);
325
326   // Converts each four consecutive pixels of the source texture into one pixel
327   // in the result texture with each pixel channel representing the grayscale
328   // color of one of the four original pixels:
329   // R1G1B1A1 R2G2B2A2 R3G3B3A3 R4G4B4A4 -> X1X2X3X4
330   // The resulting texture is still an RGBA texture (which is ~4 times narrower
331   // than the original). If rendered directly, it wouldn't show anything useful,
332   // but the data in it can be used to construct a grayscale image.
333   // |encoded_texture_size| is the exact size of the resulting RGBA texture. It
334   // is equal to src_size.width()/4 rounded upwards. Some channels in the last
335   // pixel ((-src_size.width()) % 4) to be exact) are padding and don't contain
336   // useful data.
337   // If swizzle is set to true, the transformed pixels are reordered:
338   // R1G1B1A1 R2G2B2A2 R3G3B3A3 R4G4B4A4 -> X3X2X1X4.
339   GLuint EncodeTextureAsGrayscale(GLuint src_texture,
340                                   const gfx::Size& src_size,
341                                   gfx::Size* const encoded_texture_size,
342                                   bool vertically_flip_texture,
343                                   bool swizzle);
344
345   static void nullcallback(bool success) {}
346   void ReadbackDone(Request *request, int bytes_per_pixel);
347   void FinishRequest(Request* request, bool result);
348   void CancelRequests();
349
350   static const float kRGBtoYColorWeights[];
351   static const float kRGBtoUColorWeights[];
352   static const float kRGBtoVColorWeights[];
353   static const float kRGBtoGrayscaleColorWeights[];
354
355   GLES2Interface* gl_;
356   gpu::ContextSupport* context_support_;
357   GLHelper* helper_;
358
359   // A scoped flush that will ensure all resource deletions are flushed when
360   // this object is destroyed. Must be declared before other Scoped* fields.
361   ScopedFlush flush_;
362
363   std::queue<Request*> request_queue_;
364   GLint max_draw_buffers_;
365 };
366
367 GLHelper::ScalerInterface* GLHelper::CreateScaler(ScalerQuality quality,
368                                                   const gfx::Size& src_size,
369                                                   const gfx::Rect& src_subrect,
370                                                   const gfx::Size& dst_size,
371                                                   bool vertically_flip_texture,
372                                                   bool swizzle) {
373   InitScalerImpl();
374   return scaler_impl_->CreateScaler(quality,
375                                     src_size,
376                                     src_subrect,
377                                     dst_size,
378                                     vertically_flip_texture,
379                                     swizzle);
380 }
381
382 GLuint GLHelper::CopyTextureToImpl::ScaleTexture(
383     GLuint src_texture,
384     const gfx::Size& src_size,
385     const gfx::Rect& src_subrect,
386     const gfx::Size& dst_size,
387     bool vertically_flip_texture,
388     bool swizzle,
389     SkColorType color_type,
390     GLHelper::ScalerQuality quality) {
391   GLuint dst_texture = 0u;
392   gl_->GenTextures(1, &dst_texture);
393   {
394     GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
395     ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
396
397     // Use GL_RGBA for destination/temporary texture unless we're working with
398     // 16-bit data
399     if (color_type == kRGB_565_SkColorType) {
400       format = GL_RGB;
401       type = GL_UNSIGNED_SHORT_5_6_5;
402     }
403
404     gl_->TexImage2D(GL_TEXTURE_2D,
405                     0,
406                     format,
407                     dst_size.width(),
408                     dst_size.height(),
409                     0,
410                     format,
411                     type,
412                     NULL);
413   }
414   scoped_ptr<ScalerInterface> scaler(
415       helper_->CreateScaler(quality,
416                             src_size,
417                             src_subrect,
418                             dst_size,
419                             vertically_flip_texture,
420                             swizzle));
421   scaler->Scale(src_texture, dst_texture);
422   return dst_texture;
423 }
424
425 GLuint GLHelper::CopyTextureToImpl::EncodeTextureAsGrayscale(
426     GLuint src_texture,
427     const gfx::Size& src_size,
428     gfx::Size* const encoded_texture_size,
429     bool vertically_flip_texture,
430     bool swizzle) {
431   GLuint dst_texture = 0u;
432   gl_->GenTextures(1, &dst_texture);
433   // The size of the encoded texture.
434   *encoded_texture_size =
435       gfx::Size((src_size.width() + 3) / 4, src_size.height());
436   {
437     ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
438     gl_->TexImage2D(GL_TEXTURE_2D,
439                     0,
440                     GL_RGBA,
441                     encoded_texture_size->width(),
442                     encoded_texture_size->height(),
443                     0,
444                     GL_RGBA,
445                     GL_UNSIGNED_BYTE,
446                     NULL);
447   }
448
449   helper_->InitScalerImpl();
450   scoped_ptr<ScalerInterface> grayscale_scaler(
451       helper_->scaler_impl_.get()->CreatePlanarScaler(
452           src_size,
453           gfx::Rect(0, 0, (src_size.width() + 3) & ~3, src_size.height()),
454           *encoded_texture_size,
455           vertically_flip_texture,
456           swizzle,
457           kRGBtoGrayscaleColorWeights));
458   grayscale_scaler->Scale(src_texture, dst_texture);
459   return dst_texture;
460 }
461
462 void GLHelper::CopyTextureToImpl::ReadbackAsync(
463     const gfx::Size& dst_size,
464     int32 bytes_per_row,
465     int32 row_stride_bytes,
466     unsigned char* out,
467     GLenum format,
468     GLenum type,
469     size_t bytes_per_pixel,
470     const base::Callback<void(bool)>& callback) {
471   TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::ReadbackAsync");
472   Request* request =
473       new Request(dst_size, bytes_per_row, row_stride_bytes, out, callback);
474   request_queue_.push(request);
475   request->buffer = 0u;
476
477   gl_->GenBuffers(1, &request->buffer);
478   gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer);
479   gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
480                   bytes_per_pixel * dst_size.GetArea(),
481                   NULL,
482                   GL_STREAM_READ);
483
484   request->query = 0u;
485   gl_->GenQueriesEXT(1, &request->query);
486   gl_->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, request->query);
487   gl_->ReadPixels(0,
488                   0,
489                   dst_size.width(),
490                   dst_size.height(),
491                   format,
492                   type,
493                   NULL);
494   gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM);
495   gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
496   context_support_->SignalQuery(
497       request->query,
498       base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(),
499                  request, bytes_per_pixel));
500 }
501
502 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
503     GLuint src_texture,
504     const gfx::Size& src_size,
505     const gfx::Rect& src_subrect,
506     const gfx::Size& dst_size,
507     unsigned char* out,
508     const SkColorType out_color_type,
509     const base::Callback<void(bool)>& callback,
510     GLHelper::ScalerQuality quality) {
511   GLenum format, type;
512   size_t bytes_per_pixel;
513   SkColorType readback_color_type = out_color_type;
514   // Single-component textures are not supported by all GPUs, so  we implement
515   // kAlpha_8_SkColorType support here via a special encoding (see below) using
516   // a 32-bit texture to represent an 8-bit image.
517   // Thus we use generic 32-bit readback in this case.
518   if (out_color_type == kAlpha_8_SkColorType) {
519     readback_color_type = kRGBA_8888_SkColorType;
520   }
521
522   FormatSupport supported = GetReadbackConfig(
523       readback_color_type, true, &format, &type, &bytes_per_pixel);
524
525   if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
526     callback.Run(false);
527     return;
528   }
529
530   GLuint texture = src_texture;
531
532   // Scale texture if needed
533   // Optimization: SCALER_QUALITY_FAST is just a single bilinear pass, which we
534   // can do just as well in EncodeTextureAsGrayscale, which we will do if
535   // out_color_type is kAlpha_8_SkColorType, so let's skip the scaling step
536   // in that case.
537   bool scale_texture = out_color_type != kAlpha_8_SkColorType ||
538                        quality != GLHelper::SCALER_QUALITY_FAST;
539   if (scale_texture) {
540     // Don't swizzle during the scale step for kAlpha_8_SkColorType.
541     // We will swizzle in the encode step below if needed.
542     bool scale_swizzle = out_color_type == kAlpha_8_SkColorType
543                              ? false
544                              : supported == GLHelperReadbackSupport::SWIZZLE;
545     texture =
546         ScaleTexture(src_texture,
547                      src_size,
548                      src_subrect,
549                      dst_size,
550                      true,
551                      scale_swizzle,
552                      out_color_type == kAlpha_8_SkColorType ? kN32_SkColorType
553                                                             : out_color_type,
554                      quality);
555     DCHECK(texture);
556   }
557
558   gfx::Size readback_texture_size = dst_size;
559   // Encode texture to grayscale if needed.
560   if (out_color_type == kAlpha_8_SkColorType) {
561     // Do the vertical flip here if we haven't already done it when we scaled
562     // the texture.
563     bool encode_as_grayscale_vertical_flip = !scale_texture;
564     // EncodeTextureAsGrayscale by default creates a texture which should be
565     // read back as RGBA, so need to swizzle if the readback format is BGRA.
566     bool encode_as_grayscale_swizzle = format == GL_BGRA_EXT;
567     GLuint tmp_texture =
568         EncodeTextureAsGrayscale(texture,
569                                  dst_size,
570                                  &readback_texture_size,
571                                  encode_as_grayscale_vertical_flip,
572                                  encode_as_grayscale_swizzle);
573     // If the scaled texture was created - delete it
574     if (scale_texture)
575       gl_->DeleteTextures(1, &texture);
576     texture = tmp_texture;
577     DCHECK(texture);
578   }
579
580   // Readback the pixels of the resulting texture
581   ScopedFramebuffer dst_framebuffer(gl_);
582   ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
583                                                              dst_framebuffer);
584   ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
585   gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
586                             GL_COLOR_ATTACHMENT0,
587                             GL_TEXTURE_2D,
588                             texture,
589                             0);
590
591   int32 bytes_per_row = out_color_type == kAlpha_8_SkColorType
592                             ? dst_size.width()
593                             : dst_size.width() * bytes_per_pixel;
594
595   ReadbackAsync(readback_texture_size,
596                 bytes_per_row,
597                 bytes_per_row,
598                 out,
599                 format,
600                 type,
601                 bytes_per_pixel,
602                 callback);
603   gl_->DeleteTextures(1, &texture);
604 }
605
606 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(
607     GLuint texture,
608     const gfx::Rect& src_rect,
609     unsigned char* out,
610     SkColorType color_type) {
611   GLenum format, type;
612   size_t bytes_per_pixel;
613   FormatSupport supported =
614       GetReadbackConfig(color_type, false, &format, &type, &bytes_per_pixel);
615   if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
616     return;
617   }
618
619   ScopedFramebuffer dst_framebuffer(gl_);
620   ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
621                                                              dst_framebuffer);
622   ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
623   gl_->FramebufferTexture2D(
624       GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
625   gl_->ReadPixels(src_rect.x(),
626                   src_rect.y(),
627                   src_rect.width(),
628                   src_rect.height(),
629                   format,
630                   type,
631                   out);
632 }
633
634 void GLHelper::CopyTextureToImpl::ReadbackTextureAsync(
635     GLuint texture,
636     const gfx::Size& dst_size,
637     unsigned char* out,
638     SkColorType color_type,
639     const base::Callback<void(bool)>& callback) {
640   GLenum format, type;
641   size_t bytes_per_pixel;
642   FormatSupport supported =
643       GetReadbackConfig(color_type, false, &format, &type, &bytes_per_pixel);
644   if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
645     callback.Run(false);
646     return;
647   }
648
649   ScopedFramebuffer dst_framebuffer(gl_);
650   ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
651                                                              dst_framebuffer);
652   ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
653   gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
654                             GL_COLOR_ATTACHMENT0,
655                             GL_TEXTURE_2D,
656                             texture,
657                             0);
658   ReadbackAsync(dst_size,
659                 dst_size.width() * bytes_per_pixel,
660                 dst_size.width() * bytes_per_pixel,
661                 out,
662                 format,
663                 type,
664                 bytes_per_pixel,
665                 callback);
666 }
667
668 GLuint GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
669     GLuint src_texture,
670     const gfx::Size& src_size,
671     const gfx::Size& dst_size,
672     bool vertically_flip_texture,
673     GLHelper::ScalerQuality quality) {
674   return ScaleTexture(src_texture,
675                       src_size,
676                       gfx::Rect(src_size),
677                       dst_size,
678                       vertically_flip_texture,
679                       false,
680                       kRGBA_8888_SkColorType,  // GL_RGBA
681                       quality);
682 }
683
684 void GLHelper::CopyTextureToImpl::ReadbackDone(Request* finished_request,
685                                                int bytes_per_pixel) {
686   TRACE_EVENT0("mirror",
687                "GLHelper::CopyTextureToImpl::CheckReadbackFramebufferComplete");
688   finished_request->done = true;
689
690   // We process transfer requests in the order they were received, regardless
691   // of the order we get the callbacks in.
692   while (!request_queue_.empty()) {
693     Request* request = request_queue_.front();
694     if (!request->done) {
695       break;
696     }
697
698     bool result = false;
699     if (request->buffer != 0) {
700       gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer);
701       unsigned char* data = static_cast<unsigned char*>(gl_->MapBufferCHROMIUM(
702           GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY));
703       if (data) {
704         result = true;
705         if (request->bytes_per_row == request->size.width() * bytes_per_pixel &&
706             request->bytes_per_row == request->row_stride_bytes) {
707           memcpy(request->pixels, data,
708                  request->size.GetArea() * bytes_per_pixel);
709         } else {
710           unsigned char* out = request->pixels;
711           for (int y = 0; y < request->size.height(); y++) {
712             memcpy(out, data, request->bytes_per_row);
713             out += request->row_stride_bytes;
714             data += request->size.width() * bytes_per_pixel;
715           }
716         }
717         gl_->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM);
718       }
719       gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
720     }
721     FinishRequest(request, result);
722   }
723 }
724
725 void GLHelper::CopyTextureToImpl::FinishRequest(Request* request, bool result) {
726   TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::FinishRequest");
727   DCHECK(request_queue_.front() == request);
728   request_queue_.pop();
729   request->callback.Run(result);
730   ScopedFlush flush(gl_);
731   if (request->query != 0) {
732     gl_->DeleteQueriesEXT(1, &request->query);
733     request->query = 0;
734   }
735   if (request->buffer != 0) {
736     gl_->DeleteBuffers(1, &request->buffer);
737     request->buffer = 0;
738   }
739   delete request;
740 }
741
742 void GLHelper::CopyTextureToImpl::CancelRequests() {
743   while (!request_queue_.empty()) {
744     Request* request = request_queue_.front();
745     FinishRequest(request, false);
746   }
747 }
748
749 FormatSupport GLHelper::CopyTextureToImpl::GetReadbackConfig(
750     SkColorType color_type,
751     bool can_swizzle,
752     GLenum* format,
753     GLenum* type,
754     size_t* bytes_per_pixel) {
755   return helper_->readback_support_->GetReadbackConfig(
756       color_type, can_swizzle, format, type, bytes_per_pixel);
757 }
758
759 GLHelper::GLHelper(GLES2Interface* gl, gpu::ContextSupport* context_support)
760     : gl_(gl),
761       context_support_(context_support),
762       readback_support_(new GLHelperReadbackSupport(gl)) {}
763
764 GLHelper::~GLHelper() {}
765
766 void GLHelper::CropScaleReadbackAndCleanTexture(
767     GLuint src_texture,
768     const gfx::Size& src_size,
769     const gfx::Rect& src_subrect,
770     const gfx::Size& dst_size,
771     unsigned char* out,
772     const SkColorType out_color_type,
773     const base::Callback<void(bool)>& callback,
774     GLHelper::ScalerQuality quality) {
775   InitCopyTextToImpl();
776   copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(src_texture,
777                                                           src_size,
778                                                           src_subrect,
779                                                           dst_size,
780                                                           out,
781                                                           out_color_type,
782                                                           callback,
783                                                           quality);
784 }
785
786 void GLHelper::CropScaleReadbackAndCleanMailbox(
787     const gpu::Mailbox& src_mailbox,
788     uint32 sync_point,
789     const gfx::Size& src_size,
790     const gfx::Rect& src_subrect,
791     const gfx::Size& dst_size,
792     unsigned char* out,
793     const SkColorType out_color_type,
794     const base::Callback<void(bool)>& callback,
795     GLHelper::ScalerQuality quality) {
796   GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point);
797   CropScaleReadbackAndCleanTexture(mailbox_texture,
798                                    src_size,
799                                    src_subrect,
800                                    dst_size,
801                                    out,
802                                    out_color_type,
803                                    callback,
804                                    quality);
805   gl_->DeleteTextures(1, &mailbox_texture);
806 }
807
808 void GLHelper::ReadbackTextureSync(GLuint texture,
809                                    const gfx::Rect& src_rect,
810                                    unsigned char* out,
811                                    SkColorType format) {
812   InitCopyTextToImpl();
813   copy_texture_to_impl_->ReadbackTextureSync(texture, src_rect, out, format);
814 }
815
816 void GLHelper::ReadbackTextureAsync(
817     GLuint texture,
818     const gfx::Size& dst_size,
819     unsigned char* out,
820     SkColorType color_type,
821     const base::Callback<void(bool)>& callback) {
822   InitCopyTextToImpl();
823   copy_texture_to_impl_->ReadbackTextureAsync(texture,
824                                               dst_size,
825                                               out,
826                                               color_type,
827                                               callback);
828 }
829
830 GLuint GLHelper::CopyTexture(GLuint texture, const gfx::Size& size) {
831   InitCopyTextToImpl();
832   return copy_texture_to_impl_->CopyAndScaleTexture(
833       texture, size, size, false, GLHelper::SCALER_QUALITY_FAST);
834 }
835
836 GLuint GLHelper::CopyAndScaleTexture(GLuint texture,
837                                      const gfx::Size& src_size,
838                                      const gfx::Size& dst_size,
839                                      bool vertically_flip_texture,
840                                      ScalerQuality quality) {
841   InitCopyTextToImpl();
842   return copy_texture_to_impl_->CopyAndScaleTexture(
843       texture, src_size, dst_size, vertically_flip_texture, quality);
844 }
845
846 GLuint GLHelper::CompileShaderFromSource(const GLchar* source, GLenum type) {
847   GLuint shader = gl_->CreateShader(type);
848   GLint length = strlen(source);
849   gl_->ShaderSource(shader, 1, &source, &length);
850   gl_->CompileShader(shader);
851   GLint compile_status = 0;
852   gl_->GetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
853   if (!compile_status) {
854     GLint log_length = 0;
855     gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
856     if (log_length) {
857       scoped_ptr<GLchar[]> log(new GLchar[log_length]);
858       GLsizei returned_log_length = 0;
859       gl_->GetShaderInfoLog(
860           shader, log_length, &returned_log_length, log.get());
861       LOG(ERROR) << std::string(log.get(), returned_log_length);
862     }
863     gl_->DeleteShader(shader);
864     return 0;
865   }
866   return shader;
867 }
868
869 void GLHelper::InitCopyTextToImpl() {
870   // Lazily initialize |copy_texture_to_impl_|
871   if (!copy_texture_to_impl_)
872     copy_texture_to_impl_.reset(
873         new CopyTextureToImpl(gl_, context_support_, this));
874 }
875
876 void GLHelper::InitScalerImpl() {
877   // Lazily initialize |scaler_impl_|
878   if (!scaler_impl_)
879     scaler_impl_.reset(new GLHelperScaling(gl_, this));
880 }
881
882 GLint GLHelper::MaxDrawBuffers() {
883   InitCopyTextToImpl();
884   return copy_texture_to_impl_->MaxDrawBuffers();
885 }
886
887 void GLHelper::CopySubBufferDamage(GLuint texture,
888                                    GLuint previous_texture,
889                                    const SkRegion& new_damage,
890                                    const SkRegion& old_damage) {
891   SkRegion region(old_damage);
892   if (region.op(new_damage, SkRegion::kDifference_Op)) {
893     ScopedFramebuffer dst_framebuffer(gl_);
894     ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
895                                                                dst_framebuffer);
896     ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
897     gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
898                               GL_COLOR_ATTACHMENT0,
899                               GL_TEXTURE_2D,
900                               previous_texture,
901                               0);
902     for (SkRegion::Iterator it(region); !it.done(); it.next()) {
903       const SkIRect& rect = it.rect();
904       gl_->CopyTexSubImage2D(GL_TEXTURE_2D,
905                              0,
906                              rect.x(),
907                              rect.y(),
908                              rect.x(),
909                              rect.y(),
910                              rect.width(),
911                              rect.height());
912     }
913     gl_->Flush();
914   }
915 }
916
917 GLuint GLHelper::CreateTexture() {
918   GLuint texture = 0u;
919   gl_->GenTextures(1, &texture);
920   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
921   gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
922   gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
923   gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
924   gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
925   return texture;
926 }
927
928 void GLHelper::DeleteTexture(GLuint texture_id) {
929   gl_->DeleteTextures(1, &texture_id);
930 }
931
932 uint32 GLHelper::InsertSyncPoint() { return gl_->InsertSyncPointCHROMIUM(); }
933
934 void GLHelper::WaitSyncPoint(uint32 sync_point) {
935   gl_->WaitSyncPointCHROMIUM(sync_point);
936 }
937
938 gpu::MailboxHolder GLHelper::ProduceMailboxHolderFromTexture(
939     GLuint texture_id) {
940   gpu::Mailbox mailbox;
941   gl_->GenMailboxCHROMIUM(mailbox.name);
942   gl_->ProduceTextureDirectCHROMIUM(texture_id, GL_TEXTURE_2D, mailbox.name);
943   return gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, InsertSyncPoint());
944 }
945
946 GLuint GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
947                                          uint32 sync_point) {
948   if (mailbox.IsZero())
949     return 0;
950   if (sync_point)
951     WaitSyncPoint(sync_point);
952   GLuint texture =
953       gl_->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
954   return texture;
955 }
956
957 void GLHelper::ResizeTexture(GLuint texture, const gfx::Size& size) {
958   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
959   gl_->TexImage2D(GL_TEXTURE_2D,
960                   0,
961                   GL_RGB,
962                   size.width(),
963                   size.height(),
964                   0,
965                   GL_RGB,
966                   GL_UNSIGNED_BYTE,
967                   NULL);
968 }
969
970 void GLHelper::CopyTextureSubImage(GLuint texture, const gfx::Rect& rect) {
971   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
972   gl_->CopyTexSubImage2D(GL_TEXTURE_2D,
973                          0,
974                          rect.x(),
975                          rect.y(),
976                          rect.x(),
977                          rect.y(),
978                          rect.width(),
979                          rect.height());
980 }
981
982 void GLHelper::CopyTextureFullImage(GLuint texture, const gfx::Size& size) {
983   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
984   gl_->CopyTexImage2D(
985       GL_TEXTURE_2D, 0, GL_RGB, 0, 0, size.width(), size.height(), 0);
986 }
987
988 void GLHelper::Flush() {
989   gl_->Flush();
990 }
991
992 void GLHelper::CopyTextureToImpl::ReadbackPlane(
993     TextureFrameBufferPair* source,
994     const scoped_refptr<media::VideoFrame>& target,
995     int plane,
996     int size_shift,
997     const gfx::Rect& dst_subrect,
998     ReadbackSwizzle swizzle,
999     const base::Callback<void(bool)>& callback) {
1000   gl_->BindFramebuffer(GL_FRAMEBUFFER, source->framebuffer());
1001   size_t offset = target->stride(plane) * (dst_subrect.y() >> size_shift) +
1002       (dst_subrect.x() >> size_shift);
1003   ReadbackAsync(source->size(),
1004                 dst_subrect.width() >> size_shift,
1005                 target->stride(plane),
1006                 target->data(plane) + offset,
1007                 (swizzle == kSwizzleBGRA) ? GL_BGRA_EXT : GL_RGBA,
1008                 GL_UNSIGNED_BYTE,
1009                 4,
1010                 callback);
1011 }
1012
1013 const float GLHelper::CopyTextureToImpl::kRGBtoYColorWeights[] = {
1014     0.257f, 0.504f, 0.098f, 0.0625f};
1015 const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = {
1016     -0.148f, -0.291f, 0.439f, 0.5f};
1017 const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = {
1018     0.439f, -0.368f, -0.071f, 0.5f};
1019 const float GLHelper::CopyTextureToImpl::kRGBtoGrayscaleColorWeights[] = {
1020     0.213f, 0.715f, 0.072f, 0.0f};
1021
1022 // YUV readback constructors. Initiates the main scaler pipeline and
1023 // one planar scaler for each of the Y, U and V planes.
1024 GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
1025     GLES2Interface* gl,
1026     CopyTextureToImpl* copy_impl,
1027     GLHelperScaling* scaler_impl,
1028     GLHelper::ScalerQuality quality,
1029     const gfx::Size& src_size,
1030     const gfx::Rect& src_subrect,
1031     const gfx::Size& dst_size,
1032     const gfx::Rect& dst_subrect,
1033     bool flip_vertically,
1034     ReadbackSwizzle swizzle)
1035     : gl_(gl),
1036       copy_impl_(copy_impl),
1037       dst_size_(dst_size),
1038       dst_subrect_(dst_subrect),
1039       swizzle_(swizzle),
1040       scaler_(gl,
1041               scaler_impl->CreateScaler(quality,
1042                                         src_size,
1043                                         src_subrect,
1044                                         dst_subrect.size(),
1045                                         flip_vertically,
1046                                         false)),
1047       y_(gl,
1048          scaler_impl->CreatePlanarScaler(
1049              dst_subrect.size(),
1050              gfx::Rect(0,
1051                        0,
1052                        (dst_subrect.width() + 3) & ~3,
1053                        dst_subrect.height()),
1054              gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
1055              false,
1056              (swizzle == kSwizzleBGRA),
1057              kRGBtoYColorWeights)),
1058       u_(gl,
1059          scaler_impl->CreatePlanarScaler(
1060              dst_subrect.size(),
1061              gfx::Rect(0,
1062                        0,
1063                        (dst_subrect.width() + 7) & ~7,
1064                        (dst_subrect.height() + 1) & ~1),
1065              gfx::Size((dst_subrect.width() + 7) / 8,
1066                        (dst_subrect.height() + 1) / 2),
1067              false,
1068              (swizzle == kSwizzleBGRA),
1069              kRGBtoUColorWeights)),
1070       v_(gl,
1071          scaler_impl->CreatePlanarScaler(
1072              dst_subrect.size(),
1073              gfx::Rect(0,
1074                        0,
1075                        (dst_subrect.width() + 7) & ~7,
1076                        (dst_subrect.height() + 1) & ~1),
1077              gfx::Size((dst_subrect.width() + 7) / 8,
1078                        (dst_subrect.height() + 1) / 2),
1079              false,
1080              (swizzle == kSwizzleBGRA),
1081              kRGBtoVColorWeights)) {
1082   DCHECK(!(dst_size.width() & 1));
1083   DCHECK(!(dst_size.height() & 1));
1084   DCHECK(!(dst_subrect.width() & 1));
1085   DCHECK(!(dst_subrect.height() & 1));
1086   DCHECK(!(dst_subrect.x() & 1));
1087   DCHECK(!(dst_subrect.y() & 1));
1088 }
1089
1090 static void CallbackKeepingVideoFrameAlive(
1091     scoped_refptr<media::VideoFrame> video_frame,
1092     const base::Callback<void(bool)>& callback,
1093     bool success) {
1094   callback.Run(success);
1095 }
1096
1097 void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV(
1098     const gpu::Mailbox& mailbox,
1099     uint32 sync_point,
1100     const scoped_refptr<media::VideoFrame>& target,
1101     const base::Callback<void(bool)>& callback) {
1102   GLuint mailbox_texture =
1103       copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point);
1104
1105   // Scale texture to right size.
1106   scaler_.Scale(mailbox_texture);
1107   gl_->DeleteTextures(1, &mailbox_texture);
1108
1109   // Convert the scaled texture in to Y, U and V planes.
1110   y_.Scale(scaler_.texture());
1111   u_.Scale(scaler_.texture());
1112   v_.Scale(scaler_.texture());
1113
1114   if (target->coded_size() != dst_size_) {
1115     DCHECK(target->coded_size() == dst_size_);
1116     LOG(ERROR) << "ReadbackYUV size error!";
1117     callback.Run(false);
1118     return;
1119   }
1120
1121   // Read back planes, one at a time. Keep the video frame alive while doing the
1122   // readback.
1123   copy_impl_->ReadbackPlane(y_.texture_and_framebuffer(),
1124                             target,
1125                             media::VideoFrame::kYPlane,
1126                             0,
1127                             dst_subrect_,
1128                             swizzle_,
1129                             base::Bind(&nullcallback));
1130   copy_impl_->ReadbackPlane(u_.texture_and_framebuffer(),
1131                             target,
1132                             media::VideoFrame::kUPlane,
1133                             1,
1134                             dst_subrect_,
1135                             swizzle_,
1136                             base::Bind(&nullcallback));
1137   copy_impl_->ReadbackPlane(
1138       v_.texture_and_framebuffer(),
1139       target,
1140       media::VideoFrame::kVPlane,
1141       1,
1142       dst_subrect_,
1143       swizzle_,
1144       base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
1145   gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
1146   media::LetterboxYUV(target.get(), dst_subrect_);
1147 }
1148
1149 // YUV readback constructors. Initiates the main scaler pipeline and
1150 // one planar scaler for each of the Y, U and V planes.
1151 GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT(
1152     GLES2Interface* gl,
1153     CopyTextureToImpl* copy_impl,
1154     GLHelperScaling* scaler_impl,
1155     GLHelper::ScalerQuality quality,
1156     const gfx::Size& src_size,
1157     const gfx::Rect& src_subrect,
1158     const gfx::Size& dst_size,
1159     const gfx::Rect& dst_subrect,
1160     bool flip_vertically,
1161     ReadbackSwizzle swizzle)
1162     : gl_(gl),
1163       copy_impl_(copy_impl),
1164       dst_size_(dst_size),
1165       dst_subrect_(dst_subrect),
1166       quality_(quality),
1167       swizzle_(swizzle),
1168       scaler_(gl,
1169               scaler_impl->CreateScaler(quality,
1170                                         src_size,
1171                                         src_subrect,
1172                                         dst_subrect.size(),
1173                                         false,
1174                                         false)),
1175       pass1_shader_(scaler_impl->CreateYuvMrtShader(
1176           dst_subrect.size(),
1177           gfx::Rect(0, 0, (dst_subrect.width() + 3) & ~3, dst_subrect.height()),
1178           gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
1179           flip_vertically,
1180           (swizzle == kSwizzleBGRA),
1181           GLHelperScaling::SHADER_YUV_MRT_PASS1)),
1182       pass2_shader_(scaler_impl->CreateYuvMrtShader(
1183           gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
1184           gfx::Rect(0,
1185                     0,
1186                     (dst_subrect.width() + 7) / 8 * 2,
1187                     dst_subrect.height()),
1188           gfx::Size((dst_subrect.width() + 7) / 8,
1189                     (dst_subrect.height() + 1) / 2),
1190           false,
1191           (swizzle == kSwizzleBGRA),
1192           GLHelperScaling::SHADER_YUV_MRT_PASS2)),
1193       y_(gl, gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height())),
1194       uv_(gl),
1195       u_(gl,
1196          gfx::Size((dst_subrect.width() + 7) / 8,
1197                    (dst_subrect.height() + 1) / 2)),
1198       v_(gl,
1199          gfx::Size((dst_subrect.width() + 7) / 8,
1200                    (dst_subrect.height() + 1) / 2)) {
1201
1202   content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl, uv_);
1203   gl->TexImage2D(GL_TEXTURE_2D,
1204                  0,
1205                  GL_RGBA,
1206                  (dst_subrect.width() + 3) / 4,
1207                  dst_subrect.height(),
1208                  0,
1209                  GL_RGBA,
1210                  GL_UNSIGNED_BYTE,
1211                  NULL);
1212
1213   DCHECK(!(dst_size.width() & 1));
1214   DCHECK(!(dst_size.height() & 1));
1215   DCHECK(!(dst_subrect.width() & 1));
1216   DCHECK(!(dst_subrect.height() & 1));
1217   DCHECK(!(dst_subrect.x() & 1));
1218   DCHECK(!(dst_subrect.y() & 1));
1219 }
1220
1221 void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV(
1222     const gpu::Mailbox& mailbox,
1223     uint32 sync_point,
1224     const scoped_refptr<media::VideoFrame>& target,
1225     const base::Callback<void(bool)>& callback) {
1226   GLuint mailbox_texture =
1227       copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point);
1228
1229   GLuint texture;
1230   if (quality_ == GLHelper::SCALER_QUALITY_FAST) {
1231     // Optimization: SCALER_QUALITY_FAST is just a single bilinear
1232     // pass, which pass1_shader_ can do just as well, so let's skip
1233     // the actual scaling in that case.
1234     texture = mailbox_texture;
1235   } else {
1236     // Scale texture to right size.
1237     scaler_.Scale(mailbox_texture);
1238     texture = scaler_.texture();
1239   }
1240
1241   std::vector<GLuint> outputs(2);
1242   // Convert the scaled texture in to Y, U and V planes.
1243   outputs[0] = y_.texture();
1244   outputs[1] = uv_;
1245   pass1_shader_->Execute(texture, outputs);
1246
1247   gl_->DeleteTextures(1, &mailbox_texture);
1248
1249   outputs[0] = u_.texture();
1250   outputs[1] = v_.texture();
1251   pass2_shader_->Execute(uv_, outputs);
1252
1253   if (target->coded_size() != dst_size_) {
1254     DCHECK(target->coded_size() == dst_size_);
1255     LOG(ERROR) << "ReadbackYUV size error!";
1256     callback.Run(false);
1257     return;
1258   }
1259
1260   // Read back planes, one at a time.
1261   copy_impl_->ReadbackPlane(&y_,
1262                             target,
1263                             media::VideoFrame::kYPlane,
1264                             0,
1265                             dst_subrect_,
1266                             swizzle_,
1267                             base::Bind(&nullcallback));
1268   copy_impl_->ReadbackPlane(&u_,
1269                             target,
1270                             media::VideoFrame::kUPlane,
1271                             1,
1272                             dst_subrect_,
1273                             swizzle_,
1274                             base::Bind(&nullcallback));
1275   copy_impl_->ReadbackPlane(
1276       &v_,
1277       target,
1278       media::VideoFrame::kVPlane,
1279       1,
1280       dst_subrect_,
1281       swizzle_,
1282       base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
1283   gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
1284   media::LetterboxYUV(target.get(), dst_subrect_);
1285 }
1286
1287 bool GLHelper::IsReadbackConfigSupported(SkColorType color_type) {
1288   DCHECK(readback_support_.get());
1289   GLenum format, type;
1290   size_t bytes_per_pixel;
1291   FormatSupport support = readback_support_->GetReadbackConfig(
1292       color_type, false, &format, &type, &bytes_per_pixel);
1293
1294   return (support == GLHelperReadbackSupport::SUPPORTED);
1295 }
1296
1297 ReadbackYUVInterface* GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
1298     GLHelper::ScalerQuality quality,
1299     const gfx::Size& src_size,
1300     const gfx::Rect& src_subrect,
1301     const gfx::Size& dst_size,
1302     const gfx::Rect& dst_subrect,
1303     bool flip_vertically,
1304     bool use_mrt) {
1305   helper_->InitScalerImpl();
1306   // Just query if the best readback configuration needs a swizzle In
1307   // ReadbackPlane() we will choose GL_RGBA/GL_BGRA_EXT based on swizzle
1308   GLenum format, type;
1309   size_t bytes_per_pixel;
1310   FormatSupport supported = GetReadbackConfig(
1311       kRGBA_8888_SkColorType, true, &format, &type, &bytes_per_pixel);
1312   DCHECK((format == GL_RGBA || format == GL_BGRA_EXT) &&
1313          type == GL_UNSIGNED_BYTE);
1314
1315   ReadbackSwizzle swizzle = kSwizzleNone;
1316   if (supported == GLHelperReadbackSupport::SWIZZLE)
1317     swizzle = kSwizzleBGRA;
1318
1319   if (max_draw_buffers_ >= 2 && use_mrt) {
1320     return new ReadbackYUV_MRT(gl_,
1321                                this,
1322                                helper_->scaler_impl_.get(),
1323                                quality,
1324                                src_size,
1325                                src_subrect,
1326                                dst_size,
1327                                dst_subrect,
1328                                flip_vertically,
1329                                swizzle);
1330   }
1331   return new ReadbackYUVImpl(gl_,
1332                              this,
1333                              helper_->scaler_impl_.get(),
1334                              quality,
1335                              src_size,
1336                              src_subrect,
1337                              dst_size,
1338                              dst_subrect,
1339                              flip_vertically,
1340                              swizzle);
1341 }
1342
1343 ReadbackYUVInterface* GLHelper::CreateReadbackPipelineYUV(
1344     ScalerQuality quality,
1345     const gfx::Size& src_size,
1346     const gfx::Rect& src_subrect,
1347     const gfx::Size& dst_size,
1348     const gfx::Rect& dst_subrect,
1349     bool flip_vertically,
1350     bool use_mrt) {
1351   InitCopyTextToImpl();
1352   return copy_texture_to_impl_->CreateReadbackPipelineYUV(quality,
1353                                                           src_size,
1354                                                           src_subrect,
1355                                                           dst_size,
1356                                                           dst_subrect,
1357                                                           flip_vertically,
1358                                                           use_mrt);
1359 }
1360
1361 }  // namespace content