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