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