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 GPU_COMMAND_BUFFER_CLIENT_GL_HELPER_SCALING_H_ 6 #define GPU_COMMAND_BUFFER_CLIENT_GL_HELPER_SCALING_H_ 7 8 #include <map> 9 #include <vector> 10 11 #include "base/containers/circular_deque.h" 12 #include "base/macros.h" 13 #include "gpu/command_buffer/client/gl_helper.h" 14 #include "gpu/gpu_export.h" 15 #include "ui/gfx/geometry/vector2d.h" 16 17 namespace gpu { 18 19 class GLHelperTest; 20 class ScalerImpl; 21 class ShaderProgram; 22 23 // Implements GPU texture scaling methods. 24 // Note that you should probably not use this class directly. 25 // See gl_helper.cc::CreateScaler instead. 26 class GPU_EXPORT GLHelperScaling { 27 public: 28 enum ShaderType { 29 SHADER_BILINEAR, 30 SHADER_BILINEAR2, 31 SHADER_BILINEAR3, 32 SHADER_BILINEAR4, 33 SHADER_BILINEAR2X2, 34 SHADER_BICUBIC_UPSCALE, 35 SHADER_BICUBIC_HALF_1D, 36 SHADER_PLANAR, 37 SHADER_YUV_MRT_PASS1, 38 SHADER_YUV_MRT_PASS2, 39 }; 40 41 using ShaderProgramKeyType = std::pair<ShaderType, bool>; 42 43 GLHelperScaling(gles2::GLES2Interface* gl, GLHelper* helper); 44 ~GLHelperScaling(); 45 void InitBuffer(); 46 47 // Returns null on invalid arguments. 48 std::unique_ptr<GLHelper::ScalerInterface> CreateScaler( 49 GLHelper::ScalerQuality quality, 50 const gfx::Vector2d& scale_from, 51 const gfx::Vector2d& scale_to, 52 bool flipped_source, 53 bool flip_output, 54 bool swizzle); 55 56 // These convert source textures with RGBA pixel data into a single-color- 57 // channel planar format. Used for grayscale and I420 format conversion. 58 // 59 // While these output RGBA pixels in the destination texture(s), each RGBA 60 // pixel is actually a container for 4 consecutive pixels in the result. 61 std::unique_ptr<GLHelper::ScalerInterface> CreateGrayscalePlanerizer( 62 bool flipped_source, 63 bool flip_output, 64 bool swizzle); 65 std::unique_ptr<GLHelper::ScalerInterface> CreateI420Planerizer( 66 int plane, // 0=Y, 1=U, 2=V 67 bool flipped_source, 68 bool flip_output, 69 bool swizzle); 70 71 // These are a faster path to I420 planerization, if the platform supports 72 // it. The first pass draws to two outputs simultaneously: the Y plane and an 73 // interim UV plane that is used as the input to the second pass. Then, the 74 // second pass splits the UV plane, drawing to two outputs: the final U plane 75 // and final V plane. Thus, clients should call ScaleToMultipleOutputs() on 76 // the returned instance. 77 std::unique_ptr<GLHelper::ScalerInterface> CreateI420MrtPass1Planerizer( 78 bool flipped_source, 79 bool flip_output, 80 bool swizzle); 81 std::unique_ptr<GLHelper::ScalerInterface> CreateI420MrtPass2Planerizer( 82 bool swizzle); 83 84 private: 85 // A ScaleOp represents a pass in a scaler pipeline, in one dimension. 86 // Note that when quality is GOOD, multiple scaler passes will be 87 // combined into one operation for increased performance. 88 // Exposed in the header file for testing purposes. 89 struct ScaleOp { ScaleOpScaleOp90 ScaleOp(int factor, bool x, int size) 91 : scale_factor(factor), scale_x(x), scale_size(size) {} 92 93 // Calculates the sequence of ScaleOp needed to convert an image of 94 // relative size |src| into an image of relative size |dst|. If |scale_x| is 95 // true, then the calculations are for the X axis of the image, otherwise Y. 96 // If |allow3| is true, we can use a SHADER_BILINEAR3 to replace 97 // a scale up and scale down with a 3-tap bilinear scale. 98 // The calculated ScaleOps are added to |ops|. AddOpsScaleOp99 static void AddOps(int src, 100 int dst, 101 bool scale_x, 102 bool allow3, 103 base::circular_deque<ScaleOp>* ops) { 104 int num_downscales = 0; 105 if (allow3 && dst * 3 >= src && dst * 2 < src) { 106 // Technically, this should be a scale up and then a 107 // scale down, but it makes the optimization code more 108 // complicated. 109 ops->push_back(ScaleOp(3, scale_x, dst)); 110 return; 111 } 112 while ((dst << num_downscales) < src) { 113 num_downscales++; 114 } 115 if ((dst << num_downscales) != src) { 116 ops->push_back(ScaleOp(0, scale_x, dst << num_downscales)); 117 } 118 while (num_downscales) { 119 num_downscales--; 120 ops->push_back(ScaleOp(2, scale_x, dst << num_downscales)); 121 } 122 } 123 124 // Update either the X or Y component of |scale| to the match the relative 125 // result size of this ScaleOp. UpdateScaleScaleOp126 void UpdateScale(gfx::Vector2d* scale) { 127 if (scale_x) { 128 scale->set_x(scale_size); 129 } else { 130 scale->set_y(scale_size); 131 } 132 } 133 134 // A scale factor of 0 means upscale 135 // 2 means 50% scale 136 // 3 means 33% scale, etc. 137 int scale_factor; 138 bool scale_x; // Otherwise y 139 int scale_size; // Size to scale to. 140 }; 141 142 // Full specification for a single scaling stage. 143 struct ScalerStage { 144 ShaderType shader; 145 gfx::Vector2d scale_from; 146 gfx::Vector2d scale_to; 147 bool scale_x; 148 bool flipped_source; 149 bool flip_output; 150 bool swizzle; 151 }; 152 153 // Compute a vector of scaler stages for a particular 154 // set of input/output parameters. 155 static void ComputeScalerStages(GLHelper::ScalerQuality quality, 156 const gfx::Vector2d& scale_from, 157 const gfx::Vector2d& scale_to, 158 bool flipped_source, 159 bool flip_output, 160 bool swizzle, 161 std::vector<ScalerStage>* scaler_stages); 162 163 // Take two queues of ScaleOp structs and generate a 164 // vector of scaler stages. This is the second half of 165 // ComputeScalerStages. 166 static void ConvertScalerOpsToScalerStages( 167 GLHelper::ScalerQuality quality, 168 gfx::Vector2d scale_from, 169 base::circular_deque<GLHelperScaling::ScaleOp>* x_ops, 170 base::circular_deque<GLHelperScaling::ScaleOp>* y_ops, 171 std::vector<ScalerStage>* scaler_stages); 172 173 scoped_refptr<ShaderProgram> GetShaderProgram(ShaderType type, bool swizzle); 174 175 // Interleaved array of 2-dimentional vertex positions (x, y) and 176 // 2-dimentional texture coordinates (s, t). 177 static const GLfloat kVertexAttributes[]; 178 179 gles2::GLES2Interface* gl_; 180 GLHelper* helper_; 181 182 // The buffer that holds the vertices and the texture coordinates data for 183 // drawing a quad. 184 ScopedBuffer vertex_attributes_buffer_; 185 186 std::map<ShaderProgramKeyType, scoped_refptr<ShaderProgram>> shader_programs_; 187 188 friend class ShaderProgram; 189 friend class ScalerImpl; 190 friend class GLHelperBenchmark; 191 friend class GLHelperTest; 192 DISALLOW_COPY_AND_ASSIGN(GLHelperScaling); 193 }; 194 195 } // namespace gpu 196 197 #endif // GPU_COMMAND_BUFFER_CLIENT_GL_HELPER_SCALING_H_ 198