#ifndef GPU_COMMAND_BUFFER_CLIENT_GL_HELPER_SCALING_H_
#define GPU_COMMAND_BUFFER_CLIENT_GL_HELPER_SCALING_H_
#include <map>
#include <vector>
#include "base/containers/circular_deque.h"
#include "base/memory/raw_ptr.h"
#include "gpu/command_buffer/client/gl_helper.h"
#include "gpu/command_buffer/client/gpu_command_buffer_client_export.h"
#include "ui/gfx/geometry/vector2d.h"
namespace gpu {
class GLHelperTest;
class ScalerImpl;
class ShaderProgram;
class GPU_COMMAND_BUFFER_CLIENT_EXPORT GLHelperScaling {
public:
enum ShaderType {
SHADER_BILINEAR,
SHADER_BILINEAR2,
SHADER_BILINEAR3,
SHADER_BILINEAR4,
SHADER_BILINEAR2X2,
SHADER_BICUBIC_UPSCALE,
SHADER_BICUBIC_HALF_1D,
SHADER_PLANAR,
SHADER_YUV_MRT_PASS1,
SHADER_YUV_MRT_PASS2,
};
using ShaderProgramKeyType = std::pair<ShaderType, bool>;
GLHelperScaling(gles2::GLES2Interface* gl, GLHelper* helper);
GLHelperScaling(const GLHelperScaling&) = delete;
GLHelperScaling& operator=(const GLHelperScaling&) = delete;
~GLHelperScaling();
void InitBuffer();
std::unique_ptr<GLHelper::ScalerInterface> CreateScaler(
GLHelper::ScalerQuality quality,
const gfx::Vector2d& scale_from,
const gfx::Vector2d& scale_to,
bool flipped_source,
bool flip_output,
bool swizzle);
std::unique_ptr<GLHelper::ScalerInterface> CreateGrayscalePlanerizer(
bool flipped_source,
bool flip_output,
bool swizzle);
std::unique_ptr<GLHelper::ScalerInterface> CreateI420Planerizer(
int plane,
bool flipped_source,
bool flip_output,
bool swizzle);
std::unique_ptr<GLHelper::ScalerInterface> CreateI420MrtPass1Planerizer(
bool flipped_source,
bool flip_output,
bool swizzle);
std::unique_ptr<GLHelper::ScalerInterface> CreateI420MrtPass2Planerizer(
bool swizzle);
private:
struct ScaleOp {
ScaleOp(int factor, bool x, int size)
: scale_factor(factor), scale_x(x), scale_size(size) {}
static void AddOps(int src,
int dst,
bool scale_x,
bool allow3,
base::circular_deque<ScaleOp>* ops) {
int num_downscales = 0;
if (allow3 && dst * 3 >= src && dst * 2 < src) {
ops->push_back(ScaleOp(3, scale_x, dst));
return;
}
while ((dst << num_downscales) < src) {
num_downscales++;
}
if ((dst << num_downscales) != src) {
ops->push_back(ScaleOp(0, scale_x, dst << num_downscales));
}
while (num_downscales) {
num_downscales--;
ops->push_back(ScaleOp(2, scale_x, dst << num_downscales));
}
}
void UpdateScale(gfx::Vector2d* scale) {
if (scale_x) {
scale->set_x(scale_size);
} else {
scale->set_y(scale_size);
}
}
int scale_factor;
bool scale_x;
int scale_size;
};
struct ScalerStage {
ShaderType shader;
gfx::Vector2d scale_from;
gfx::Vector2d scale_to;
bool scale_x;
bool flipped_source;
bool flip_output;
bool swizzle;
};
static void ComputeScalerStages(GLHelper::ScalerQuality quality,
const gfx::Vector2d& scale_from,
const gfx::Vector2d& scale_to,
bool flipped_source,
bool flip_output,
bool swizzle,
std::vector<ScalerStage>* scaler_stages);
static void ConvertScalerOpsToScalerStages(
GLHelper::ScalerQuality quality,
gfx::Vector2d scale_from,
base::circular_deque<GLHelperScaling::ScaleOp>* x_ops,
base::circular_deque<GLHelperScaling::ScaleOp>* y_ops,
std::vector<ScalerStage>* scaler_stages);
scoped_refptr<ShaderProgram> GetShaderProgram(ShaderType type, bool swizzle);
static const GLfloat kVertexAttributes[];
raw_ptr<gles2::GLES2Interface> gl_;
raw_ptr<GLHelper> helper_;
ScopedBuffer vertex_attributes_buffer_;
std::map<ShaderProgramKeyType, scoped_refptr<ShaderProgram>> shader_programs_;
friend class ShaderProgram;
friend class ScalerImpl;
friend class GLHelperBenchmark;
friend class GLHelperTest;
};
}
#endif