Home | History | Annotate | Download | only in client
      1 // Copyright (c) 2013 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_SCALING_H_
      6 #define CONTENT_COMMON_GPU_CLIENT_GL_HELPER_SCALING_H_
      7 
      8 #include <vector>
      9 
     10 #include "content/common/gpu/client/gl_helper.h"
     11 
     12 namespace content {
     13 
     14 class ShaderProgram;
     15 class ScalerImpl;
     16 class GLHelperTest;
     17 
     18 // Implements GPU texture scaling methods.
     19 // Note that you should probably not use this class directly.
     20 // See gl_helper.cc::CreateScaler instead.
     21 class CONTENT_EXPORT GLHelperScaling {
     22  public:
     23   enum ShaderType {
     24     SHADER_BILINEAR,
     25     SHADER_BILINEAR2,
     26     SHADER_BILINEAR3,
     27     SHADER_BILINEAR4,
     28     SHADER_BILINEAR2X2,
     29     SHADER_BICUBIC_UPSCALE,
     30     SHADER_BICUBIC_HALF_1D,
     31     SHADER_PLANAR,
     32     SHADER_YUV_MRT_PASS1,
     33     SHADER_YUV_MRT_PASS2,
     34   };
     35 
     36   // Similar to ScalerInterface, but can generate multiple outputs.
     37   // Used for YUV conversion in gl_helper.c
     38   class CONTENT_EXPORT ShaderInterface {
     39    public:
     40     ShaderInterface() {}
     41     virtual ~ShaderInterface() {}
     42     // Note that the src_texture will have the min/mag filter set to GL_LINEAR
     43     // and wrap_s/t set to CLAMP_TO_EDGE in this call.
     44     virtual void Execute(blink::WebGLId source_texture,
     45                          const std::vector<blink::WebGLId>& dest_textures) = 0;
     46   };
     47 
     48   typedef std::pair<ShaderType, bool> ShaderProgramKeyType;
     49 
     50   GLHelperScaling(blink::WebGraphicsContext3D* context,
     51                   GLHelper* helper);
     52   ~GLHelperScaling();
     53   void InitBuffer();
     54 
     55   GLHelper::ScalerInterface* CreateScaler(
     56       GLHelper::ScalerQuality quality,
     57       gfx::Size src_size,
     58       gfx::Rect src_subrect,
     59       const gfx::Size& dst_size,
     60       bool vertically_flip_texture,
     61       bool swizzle);
     62 
     63   GLHelper::ScalerInterface* CreatePlanarScaler(
     64       const gfx::Size& src_size,
     65       const gfx::Rect& src_subrect,
     66       const gfx::Size& dst_size,
     67       bool vertically_flip_texture,
     68       const float color_weights[4]);
     69 
     70   ShaderInterface* CreateYuvMrtShader(
     71       const gfx::Size& src_size,
     72       const gfx::Rect& src_subrect,
     73       const gfx::Size& dst_size,
     74       bool vertically_flip_texture,
     75       ShaderType shader);
     76 
     77  private:
     78   // A ScaleOp represents a pass in a scaler pipeline, in one dimension.
     79   // Note that when quality is GOOD, multiple scaler passes will be
     80   // combined into one operation for increased performance.
     81   // Exposed in the header file for testing purposes.
     82   struct ScaleOp {
     83     ScaleOp(int factor, bool x, int size)
     84         : scale_factor(factor), scale_x(x), scale_size(size) {
     85     }
     86 
     87     // Calculate a set of ScaleOp needed to convert an image of size
     88     // |src| into an image of size |dst|. If |scale_x| is true, then
     89     // the calculations are for the X axis of the image, otherwise Y.
     90     // If |allow3| is true, we can use a SHADER_BILINEAR3 to replace
     91     // a scale up and scale down with a 3-tap bilinear scale.
     92     // The calculated ScaleOps are added to |ops|.
     93     static void AddOps(int src,
     94                        int dst,
     95                        bool scale_x,
     96                        bool allow3,
     97                        std::deque<ScaleOp>* ops) {
     98       int num_downscales = 0;
     99       if (allow3 && dst * 3 >= src && dst * 2 < src) {
    100         // Technically, this should be a scale up and then a
    101         // scale down, but it makes the optimization code more
    102         // complicated.
    103         ops->push_back(ScaleOp(3, scale_x, dst));
    104         return;
    105       }
    106       while ((dst << num_downscales) < src) {
    107         num_downscales++;
    108       }
    109       if ((dst << num_downscales) != src) {
    110         ops->push_back(ScaleOp(0, scale_x, dst << num_downscales));
    111       }
    112       while (num_downscales) {
    113         num_downscales--;
    114         ops->push_back(ScaleOp(2, scale_x, dst << num_downscales));
    115       }
    116     }
    117 
    118     // Update |size| to its new size. Before calling this function
    119     // |size| should be the size of the input image. After calling it,
    120     // |size| will be the size of the image after this particular
    121     // scaling operation.
    122     void UpdateSize(gfx::Size* subrect) {
    123       if (scale_x) {
    124         subrect->set_width(scale_size);
    125       } else {
    126         subrect->set_height(scale_size);
    127       }
    128     }
    129 
    130     // A scale factor of 0 means upscale
    131     // 2 means 50% scale
    132     // 3 means 33% scale, etc.
    133     int scale_factor;
    134     bool scale_x;  // Otherwise y
    135     int scale_size;  // Size to scale to.
    136   };
    137 
    138   // Full specification for a single scaling stage.
    139   struct ScalerStage {
    140     ScalerStage(ShaderType shader_,
    141                 gfx::Size src_size_,
    142                 gfx::Rect src_subrect_,
    143                 gfx::Size dst_size_,
    144                 bool scale_x_,
    145                 bool vertically_flip_texture_,
    146                 bool swizzle_);
    147     ShaderType shader;
    148     gfx::Size src_size;
    149     gfx::Rect src_subrect;
    150     gfx::Size dst_size;
    151     bool scale_x;
    152     bool vertically_flip_texture;
    153     bool swizzle;
    154   };
    155 
    156   // Compute a vector of scaler stages for a particular
    157   // set of input/output parameters.
    158   void ComputeScalerStages(GLHelper::ScalerQuality quality,
    159                            const gfx::Size& src_size,
    160                            const gfx::Rect& src_subrect,
    161                            const gfx::Size& dst_size,
    162                            bool vertically_flip_texture,
    163                            bool swizzle,
    164                            std::vector<ScalerStage> *scaler_stages);
    165 
    166   // Take two queues of ScaleOp structs and generate a
    167   // vector of scaler stages. This is the second half of
    168   // ComputeScalerStages.
    169   void ConvertScalerOpsToScalerStages(
    170       GLHelper::ScalerQuality quality,
    171       gfx::Size src_size,
    172       gfx::Rect src_subrect,
    173       const gfx::Size& dst_size,
    174       bool vertically_flip_texture,
    175       bool swizzle,
    176       std::deque<GLHelperScaling::ScaleOp>* x_ops,
    177       std::deque<GLHelperScaling::ScaleOp>* y_ops,
    178       std::vector<ScalerStage> *scaler_stages);
    179 
    180 
    181   scoped_refptr<ShaderProgram> GetShaderProgram(ShaderType type, bool swizzle);
    182 
    183   // Interleaved array of 2-dimentional vertex positions (x, y) and
    184   // 2-dimentional texture coordinates (s, t).
    185   static const blink::WGC3Dfloat kVertexAttributes[];
    186 
    187   blink::WebGraphicsContext3D* context_;
    188   GLHelper* helper_;
    189 
    190   // The buffer that holds the vertices and the texture coordinates data for
    191   // drawing a quad.
    192   ScopedBuffer vertex_attributes_buffer_;
    193 
    194   std::map<ShaderProgramKeyType,
    195            scoped_refptr<ShaderProgram> > shader_programs_;
    196 
    197   friend class ShaderProgram;
    198   friend class ScalerImpl;
    199   friend class GLHelperTest;
    200   DISALLOW_COPY_AND_ASSIGN(GLHelperScaling);
    201 };
    202 
    203 
    204 }  // namespace content
    205 
    206 #endif  // CONTENT_COMMON_GPU_CLIENT_GL_HELPER_SCALING_H_
    207