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