• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_
6 #define CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_
7 
8 #include "base/atomicops.h"
9 #include "base/basictypes.h"
10 #include "base/callback.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "content/common/content_export.h"
13 #include "gpu/command_buffer/client/gles2_interface.h"
14 #include "gpu/command_buffer/common/mailbox_holder.h"
15 #include "third_party/skia/include/core/SkBitmap.h"
16 
17 namespace gfx {
18 class Rect;
19 class Size;
20 }
21 
22 namespace gpu {
23 class ContextSupport;
24 struct Mailbox;
25 }
26 
27 namespace media {
28 class VideoFrame;
29 };
30 
31 class SkRegion;
32 
33 namespace content {
34 
35 class GLHelperScaling;
36 
37 class ScopedGLuint {
38  public:
39   typedef void (gpu::gles2::GLES2Interface::*GenFunc)(GLsizei n, GLuint* ids);
40   typedef void (gpu::gles2::GLES2Interface::*DeleteFunc)(GLsizei n,
41                                                          const GLuint* ids);
ScopedGLuint(gpu::gles2::GLES2Interface * gl,GenFunc gen_func,DeleteFunc delete_func)42   ScopedGLuint(gpu::gles2::GLES2Interface* gl,
43                GenFunc gen_func,
44                DeleteFunc delete_func)
45       : gl_(gl), id_(0u), delete_func_(delete_func) {
46     (gl_->*gen_func)(1, &id_);
47   }
48 
GLuint()49   operator GLuint() const { return id_; }
50 
id()51   GLuint id() const { return id_; }
52 
~ScopedGLuint()53   ~ScopedGLuint() {
54     if (id_ != 0) {
55       (gl_->*delete_func_)(1, &id_);
56     }
57   }
58 
59  private:
60   gpu::gles2::GLES2Interface* gl_;
61   GLuint id_;
62   DeleteFunc delete_func_;
63 
64   DISALLOW_COPY_AND_ASSIGN(ScopedGLuint);
65 };
66 
67 class ScopedBuffer : public ScopedGLuint {
68  public:
ScopedBuffer(gpu::gles2::GLES2Interface * gl)69   explicit ScopedBuffer(gpu::gles2::GLES2Interface* gl)
70       : ScopedGLuint(gl,
71                      &gpu::gles2::GLES2Interface::GenBuffers,
72                      &gpu::gles2::GLES2Interface::DeleteBuffers) {}
73 };
74 
75 class ScopedFramebuffer : public ScopedGLuint {
76  public:
ScopedFramebuffer(gpu::gles2::GLES2Interface * gl)77   explicit ScopedFramebuffer(gpu::gles2::GLES2Interface* gl)
78       : ScopedGLuint(gl,
79                      &gpu::gles2::GLES2Interface::GenFramebuffers,
80                      &gpu::gles2::GLES2Interface::DeleteFramebuffers) {}
81 };
82 
83 class ScopedTexture : public ScopedGLuint {
84  public:
ScopedTexture(gpu::gles2::GLES2Interface * gl)85   explicit ScopedTexture(gpu::gles2::GLES2Interface* gl)
86       : ScopedGLuint(gl,
87                      &gpu::gles2::GLES2Interface::GenTextures,
88                      &gpu::gles2::GLES2Interface::DeleteTextures) {}
89 };
90 
91 template <GLenum Target>
92 class ScopedBinder {
93  public:
94   typedef void (gpu::gles2::GLES2Interface::*BindFunc)(GLenum target,
95                                                        GLuint id);
ScopedBinder(gpu::gles2::GLES2Interface * gl,GLuint id,BindFunc bind_func)96   ScopedBinder(gpu::gles2::GLES2Interface* gl, GLuint id, BindFunc bind_func)
97       : gl_(gl), bind_func_(bind_func) {
98     (gl_->*bind_func_)(Target, id);
99   }
100 
~ScopedBinder()101   virtual ~ScopedBinder() { (gl_->*bind_func_)(Target, 0); }
102 
103  private:
104   gpu::gles2::GLES2Interface* gl_;
105   BindFunc bind_func_;
106 
107   DISALLOW_COPY_AND_ASSIGN(ScopedBinder);
108 };
109 
110 template <GLenum Target>
111 class ScopedBufferBinder : ScopedBinder<Target> {
112  public:
ScopedBufferBinder(gpu::gles2::GLES2Interface * gl,GLuint id)113   ScopedBufferBinder(gpu::gles2::GLES2Interface* gl, GLuint id)
114       : ScopedBinder<Target>(gl, id, &gpu::gles2::GLES2Interface::BindBuffer) {}
115 };
116 
117 template <GLenum Target>
118 class ScopedFramebufferBinder : ScopedBinder<Target> {
119  public:
ScopedFramebufferBinder(gpu::gles2::GLES2Interface * gl,GLuint id)120   ScopedFramebufferBinder(gpu::gles2::GLES2Interface* gl, GLuint id)
121       : ScopedBinder<Target>(gl,
122                              id,
123                              &gpu::gles2::GLES2Interface::BindFramebuffer) {}
124 };
125 
126 template <GLenum Target>
127 class ScopedTextureBinder : ScopedBinder<Target> {
128  public:
ScopedTextureBinder(gpu::gles2::GLES2Interface * gl,GLuint id)129   ScopedTextureBinder(gpu::gles2::GLES2Interface* gl, GLuint id)
130       : ScopedBinder<Target>(gl, id, &gpu::gles2::GLES2Interface::BindTexture) {
131   }
132 };
133 
134 class ReadbackYUVInterface;
135 class GLHelperReadbackSupport;
136 
137 // Provides higher level operations on top of the gpu::gles2::GLES2Interface
138 // interfaces.
139 class CONTENT_EXPORT GLHelper {
140  public:
141   GLHelper(gpu::gles2::GLES2Interface* gl,
142            gpu::ContextSupport* context_support);
143   ~GLHelper();
144 
145   enum ScalerQuality {
146     // Bilinear single pass, fastest possible.
147     SCALER_QUALITY_FAST = 1,
148 
149     // Bilinear upscale + N * 50% bilinear downscales.
150     // This is still fast enough for most purposes and
151     // Image quality is nearly as good as the BEST option.
152     SCALER_QUALITY_GOOD = 2,
153 
154     // Bicubic upscale + N * 50% bicubic downscales.
155     // Produces very good quality scaled images, but it's
156     // 2-8x slower than the "GOOD" quality, so it's not always
157     // worth it.
158     SCALER_QUALITY_BEST = 3,
159   };
160 
161   // Copies the block of pixels specified with |src_subrect| from |src_texture|,
162   // scales it to |dst_size|, and writes it into |out|.
163   // |src_size| is the size of |src_texture|. The result is of format GL_BGRA
164   // and is potentially flipped vertically to make it a correct image
165   // representation.  |callback| is invoked with the copy result when the copy
166   // operation has completed.
167   // Note that the src_texture will have the min/mag filter set to GL_LINEAR
168   // and wrap_s/t set to CLAMP_TO_EDGE in this call.
169   void CropScaleReadbackAndCleanTexture(
170       GLuint src_texture,
171       const gfx::Size& src_size,
172       const gfx::Rect& src_subrect,
173       const gfx::Size& dst_size,
174       unsigned char* out,
175       const SkBitmap::Config config,
176       const base::Callback<void(bool)>& callback,
177       GLHelper::ScalerQuality quality);
178 
179   // Copies the block of pixels specified with |src_subrect| from |src_mailbox|,
180   // scales it to |dst_size|, and writes it into |out|.
181   // |src_size| is the size of |src_mailbox|. The result is of format GL_BGRA
182   // and is potentially flipped vertically to make it a correct image
183   // representation.  |callback| is invoked with the copy result when the copy
184   // operation has completed.
185   // Note that the texture bound to src_mailbox will have the min/mag filter set
186   // to GL_LINEAR and wrap_s/t set to CLAMP_TO_EDGE in this call. src_mailbox is
187   // assumed to be GL_TEXTURE_2D.
188   void CropScaleReadbackAndCleanMailbox(
189       const gpu::Mailbox& src_mailbox,
190       uint32 sync_point,
191       const gfx::Size& src_size,
192       const gfx::Rect& src_subrect,
193       const gfx::Size& dst_size,
194       unsigned char* out,
195       const SkBitmap::Config config,
196       const base::Callback<void(bool)>& callback,
197       GLHelper::ScalerQuality quality);
198 
199   // Copies the texture data out of |texture| into |out|.  |size| is the
200   // size of the texture.  No post processing is applied to the pixels.  The
201   // texture is assumed to have a format of GL_RGBA with a pixel type of
202   // GL_UNSIGNED_BYTE.  This is a blocking call that calls glReadPixels on the
203   // current OpenGL context.
204   void ReadbackTextureSync(GLuint texture,
205                            const gfx::Rect& src_rect,
206                            unsigned char* out,
207                            SkBitmap::Config format);
208 
209   void ReadbackTextureAsync(GLuint texture,
210                             const gfx::Size& dst_size,
211                             unsigned char* out,
212                             SkBitmap::Config config,
213                             const base::Callback<void(bool)>& callback);
214 
215   // Creates a copy of the specified texture. |size| is the size of the texture.
216   // Note that the src_texture will have the min/mag filter set to GL_LINEAR
217   // and wrap_s/t set to CLAMP_TO_EDGE in this call.
218   GLuint CopyTexture(GLuint texture, const gfx::Size& size);
219 
220   // Creates a scaled copy of the specified texture. |src_size| is the size of
221   // the texture and |dst_size| is the size of the resulting copy.
222   // Note that the src_texture will have the min/mag filter set to GL_LINEAR
223   // and wrap_s/t set to CLAMP_TO_EDGE in this call.
224   GLuint CopyAndScaleTexture(GLuint texture,
225                              const gfx::Size& src_size,
226                              const gfx::Size& dst_size,
227                              bool vertically_flip_texture,
228                              ScalerQuality quality);
229 
230   // Returns the shader compiled from the source.
231   GLuint CompileShaderFromSource(const GLchar* source, GLenum type);
232 
233   // Copies all pixels from |previous_texture| into |texture| that are
234   // inside the region covered by |old_damage| but not part of |new_damage|.
235   void CopySubBufferDamage(GLuint texture,
236                            GLuint previous_texture,
237                            const SkRegion& new_damage,
238                            const SkRegion& old_damage);
239 
240   // Simply creates a texture.
241   GLuint CreateTexture();
242   // Deletes a texture.
243   void DeleteTexture(GLuint texture_id);
244 
245   // Insert a sync point into the GL command buffer.
246   uint32 InsertSyncPoint();
247   // Wait for the sync point before executing further GL commands.
248   void WaitSyncPoint(uint32 sync_point);
249 
250   // Creates a mailbox holder that is attached to the given texture id, with a
251   // sync point to wait on before using the mailbox. Returns a holder with an
252   // empty mailbox on failure.
253   // Note the texture is assumed to be GL_TEXTURE_2D.
254   gpu::MailboxHolder ProduceMailboxHolderFromTexture(GLuint texture_id);
255 
256   // Creates a texture and consumes a mailbox into it. Returns 0 on failure.
257   // Note the mailbox is assumed to be GL_TEXTURE_2D.
258   GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
259                                  uint32 sync_point);
260 
261   // Resizes the texture's size to |size|.
262   void ResizeTexture(GLuint texture, const gfx::Size& size);
263 
264   // Copies the framebuffer data given in |rect| to |texture|.
265   void CopyTextureSubImage(GLuint texture, const gfx::Rect& rect);
266 
267   // Copies the all framebuffer data to |texture|. |size| specifies the
268   // size of the framebuffer.
269   void CopyTextureFullImage(GLuint texture, const gfx::Size& size);
270 
271   // Flushes GL commands.
272   void Flush();
273 
274 
275   // A scaler will cache all intermediate textures and programs
276   // needed to scale from a specified size to a destination size.
277   // If the source or destination sizes changes, you must create
278   // a new scaler.
279   class CONTENT_EXPORT ScalerInterface {
280    public:
ScalerInterface()281     ScalerInterface() {}
~ScalerInterface()282     virtual ~ScalerInterface() {}
283 
284     // Note that the src_texture will have the min/mag filter set to GL_LINEAR
285     // and wrap_s/t set to CLAMP_TO_EDGE in this call.
286     virtual void Scale(GLuint source_texture, GLuint dest_texture) = 0;
287     virtual const gfx::Size& SrcSize() = 0;
288     virtual const gfx::Rect& SrcSubrect() = 0;
289     virtual const gfx::Size& DstSize() = 0;
290   };
291 
292   // Note that the quality may be adjusted down if texture
293   // allocations fail or hardware doesn't support the requtested
294   // quality. Note that ScalerQuality enum is arranged in
295   // numerical order for simplicity.
296   ScalerInterface* CreateScaler(ScalerQuality quality,
297                                 const gfx::Size& src_size,
298                                 const gfx::Rect& src_subrect,
299                                 const gfx::Size& dst_size,
300                                 bool vertically_flip_texture,
301                                 bool swizzle);
302 
303   // Create a readback pipeline that will scale a subsection of the source
304   // texture, then convert it to YUV422 planar form and then read back that.
305   // This reduces the amount of memory read from GPU to CPU memory by a factor
306   // 2.6, which can be quite handy since readbacks have very limited speed
307   // on some platforms. All values in |dst_size| and |dst_subrect| must be
308   // a multiple of two. If |use_mrt| is true, the pipeline will try to optimize
309   // the YUV conversion using the multi-render-target extension. |use_mrt|
310   // should only be set to false for testing.
311   ReadbackYUVInterface* CreateReadbackPipelineYUV(ScalerQuality quality,
312                                                   const gfx::Size& src_size,
313                                                   const gfx::Rect& src_subrect,
314                                                   const gfx::Size& dst_size,
315                                                   const gfx::Rect& dst_subrect,
316                                                   bool flip_vertically,
317                                                   bool use_mrt);
318 
319   // Returns the maximum number of draw buffers available,
320   // 0 if GL_EXT_draw_buffers is not available.
321   GLint MaxDrawBuffers();
322 
323   // Checks whether the readbback is supported for texture with the
324   // matching config. This doesnt check for cross format readbacks.
325   bool IsReadbackConfigSupported(SkBitmap::Config texture_format);
326 
327  protected:
328   class CopyTextureToImpl;
329 
330   // Creates |copy_texture_to_impl_| if NULL.
331   void InitCopyTextToImpl();
332   // Creates |scaler_impl_| if NULL.
333   void InitScalerImpl();
334 
335   enum ReadbackSwizzle {
336     kSwizzleNone = 0,
337     kSwizzleBGRA
338   };
339 
340   gpu::gles2::GLES2Interface* gl_;
341   gpu::ContextSupport* context_support_;
342   scoped_ptr<CopyTextureToImpl> copy_texture_to_impl_;
343   scoped_ptr<GLHelperScaling> scaler_impl_;
344   scoped_ptr<GLHelperReadbackSupport> readback_support_;
345 
346   DISALLOW_COPY_AND_ASSIGN(GLHelper);
347 };
348 
349 // Similar to a ScalerInterface, a yuv readback pipeline will
350 // cache a scaler and all intermediate textures and frame buffers
351 // needed to scale, crop, letterbox and read back a texture from
352 // the GPU into CPU-accessible RAM. A single readback pipeline
353 // can handle multiple outstanding readbacks at the same time, but
354 // if the source or destination sizes change, you'll need to create
355 // a new readback pipeline.
356 class CONTENT_EXPORT ReadbackYUVInterface {
357  public:
ReadbackYUVInterface()358   ReadbackYUVInterface() {}
~ReadbackYUVInterface()359   virtual ~ReadbackYUVInterface() {}
360 
361   // Note that |target| must use YV12 format.
362   virtual void ReadbackYUV(const gpu::Mailbox& mailbox,
363                            uint32 sync_point,
364                            const scoped_refptr<media::VideoFrame>& target,
365                            const base::Callback<void(bool)>& callback) = 0;
366   virtual GLHelper::ScalerInterface* scaler() = 0;
367 };
368 
369 }  // namespace content
370 
371 #endif  // CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_
372