| Index: cc/output/shader.cc
|
| diff --git a/cc/output/shader.cc b/cc/output/shader.cc
|
| index b5d163862d14e010aa19d5bcd083278366ed34b4..a34ce07bad174bcf9a20f44831f26a2681b267be 100644
|
| --- a/cc/output/shader.cc
|
| +++ b/cc/output/shader.cc
|
| @@ -2028,9 +2028,11 @@ FragmentShaderYUVVideo::FragmentShaderYUVVideo()
|
| resource_multiplier_location_(-1),
|
| resource_offset_location_(-1) {}
|
|
|
| -void FragmentShaderYUVVideo::SetFeatures(bool use_alpha_texture,
|
| +void FragmentShaderYUVVideo::SetFeatures(SamplerType sampler,
|
| + bool use_alpha_texture,
|
| bool use_nv12,
|
| bool use_color_lut) {
|
| + sampler_ = sampler;
|
| use_alpha_texture_ = use_alpha_texture;
|
| use_nv12_ = use_nv12;
|
| use_color_lut_ = use_color_lut;
|
| @@ -2050,6 +2052,8 @@ void FragmentShaderYUVVideo::Init(GLES2Interface* context,
|
| "resource_offset",
|
| "yuv_matrix",
|
| "yuv_adj",
|
| + "ya_size",
|
| + "uv_subsampling_factor",
|
| "alpha",
|
| "ya_clamp_rect",
|
| "uv_clamp_rect",
|
| @@ -2080,9 +2084,14 @@ void FragmentShaderYUVVideo::Init(GLES2Interface* context,
|
| yuv_matrix_location_ = locations[8];
|
| yuv_adj_location_ = locations[9];
|
| }
|
| - alpha_location_ = locations[10];
|
| - ya_clamp_rect_location_ = locations[11];
|
| - uv_clamp_rect_location_ = locations[12];
|
| + if (sampler_ != SAMPLER_TYPE_2D_RECT) {
|
| + ya_size_location_ = locations[10];
|
| + } else {
|
| + uv_subsampling_factor_location_ = locations[11];
|
| + }
|
| + alpha_location_ = locations[12];
|
| + ya_clamp_rect_location_ = locations[13];
|
| + uv_clamp_rect_location_ = locations[14];
|
| }
|
|
|
| std::string FragmentShaderYUVVideo::GetShaderString(TexCoordPrecision precision,
|
| @@ -2097,13 +2106,87 @@ std::string FragmentShaderYUVVideo::GetShaderString(TexCoordPrecision precision,
|
| uniform vec4 ya_clamp_rect;
|
| uniform vec4 uv_clamp_rect;
|
| });
|
| -
|
| - std::string functions = "";
|
| + // SHADER0 cannot handle #define
|
| + head += "\n";
|
| + head += " #define PLANE_TYPE int\n";
|
| + head += " #define YA 1\n";
|
| + head += " #define UV 2\n";
|
| +
|
| + std::string functions = SHADER0([]() {
|
| + vec2 TextureLookupBilinearInternal(SamplerType sampler, vec2 snap_tex_coord,
|
| + vec2 unit_texel, vec2 factor) {
|
| + vec2 s1 = TextureLookup(sampler, snap_tex_coord).xy;
|
| + vec2 s2 =
|
| + TextureLookup(sampler, snap_tex_coord + vec2(unit_texel.x, 0.)).xy;
|
| + vec2 s3 =
|
| + TextureLookup(sampler, snap_tex_coord + vec2(0., unit_texel.y)).xy;
|
| + vec2 s4 = TextureLookup(sampler, snap_tex_coord + unit_texel).xy;
|
| + return mix(mix(s1, s2, factor.x), mix(s3, s4, factor.x), factor.y);
|
| + }
|
| + });
|
| + if (sampler_ == SAMPLER_TYPE_2D_RECT) {
|
| + head += " uniform vec2 uv_subsampling_factor;\n";
|
| + functions += SHADER0([]() {
|
| + vec2 TextureLookupBilinear(SamplerType sampler, vec2 tex_coord,
|
| + PLANE_TYPE type) {
|
| + vec2 ya_tex_coord = tex_coord;
|
| + if (type == UV) {
|
| + ya_tex_coord = tex_coord / uv_subsampling_factor;
|
| + }
|
| + vec2 unnorm_tex_coord = ya_tex_coord - vec2(0.5);
|
| + vec2 f = fract(unnorm_tex_coord);
|
| + vec2 texel_offset = floor(unnorm_tex_coord) - floor(ya_tex_coord);
|
| + vec2 unit_texel = vec2(1.);
|
| + if (type == UV) {
|
| + texel_offset = texel_offset * uv_subsampling_factor;
|
| + unit_texel = unit_texel * uv_subsampling_factor;
|
| + }
|
| + vec2 snap_tex_coord =
|
| + floor(tex_coord) + (unit_texel * 0.5) + texel_offset;
|
| + return TextureLookupBilinearInternal(sampler, snap_tex_coord,
|
| + unit_texel, f);
|
| + }
|
| + });
|
| + } else {
|
| + head += " uniform vec2 ya_size;\n";
|
| + functions += SHADER0([]() {
|
| + // refer to Mesa sample_2d_linear() in s_texfilter.c
|
| + // https://cs.chromium.org/chromium/src/third_party/mesa/src/src/mesa/swrast/s_texfilter.c?q=sample_2d_linear&sq=package:chromium
|
| + //
|
| + // This shader needs a custom bilinear filter because U plane can be
|
| + // smaller than Y plane.
|
| + // For example, look at the following figures. When the current fragment
|
| + // samples the middle point of (3, 3) texel of Y texture, it points out
|
| + // upper left of (1, 1) texel of U texture. The default GL_LINEAR samples
|
| + // 4 texels of U plane, while it samples only (3, 3) texel of Y plane.
|
| + // TextureLookupBilinear() samples U plane with Y plane fraction to
|
| + // sample like Y plane.
|
| + // Y 4x4 U 2x2 U sampling by GL_LINEAR
|
| + // +-+-+-+-+ +--+--+ +--+--+
|
| + // | | | | | | | | | | |
|
| + // +-------+ | | | | +--++
|
| + // | | | | | +-----+ +-----|
|
| + // +-------+ | |· | | ||·||
|
| + // | | |·| | | | | | +--+|
|
| + // +-------+ +--+--+ +-----+
|
| + // | | | | |
|
| + // +-+-+-+-+
|
| + vec2 TextureLookupBilinear(SamplerType sampler, vec2 tex_coord,
|
| + PLANE_TYPE type) {
|
| + vec2 unit_texel = 1.0 / ya_size;
|
| + vec2 unnorm_tex_coord = (tex_coord * ya_size) - vec2(0.5);
|
| + vec2 f = fract(unnorm_tex_coord);
|
| + vec2 snap_tex_coord = (floor(unnorm_tex_coord) + vec2(0.5)) / ya_size;
|
| + return TextureLookupBilinearInternal(sampler, snap_tex_coord,
|
| + unit_texel, f);
|
| + }
|
| + });
|
| + }
|
| if (use_nv12_) {
|
| head += " uniform SamplerType uv_texture;\n";
|
| functions += SHADER0([]() {
|
| vec2 GetUV(vec2 uv_clamped) {
|
| - return TextureLookup(uv_texture, uv_clamped).xy;
|
| + return TextureLookupBilinear(uv_texture, uv_clamped, UV);
|
| }
|
| });
|
| } else {
|
| @@ -2111,8 +2194,8 @@ std::string FragmentShaderYUVVideo::GetShaderString(TexCoordPrecision precision,
|
| head += " uniform SamplerType v_texture;\n";
|
| functions += SHADER0([]() {
|
| vec2 GetUV(vec2 uv_clamped) {
|
| - return vec2(TextureLookup(u_texture, uv_clamped).x,
|
| - TextureLookup(v_texture, uv_clamped).x);
|
| + return vec2(TextureLookupBilinear(u_texture, uv_clamped, UV).x,
|
| + TextureLookupBilinear(v_texture, uv_clamped, UV).x);
|
| }
|
| });
|
| }
|
| @@ -2121,7 +2204,7 @@ std::string FragmentShaderYUVVideo::GetShaderString(TexCoordPrecision precision,
|
| head += " uniform SamplerType a_texture;\n";
|
| functions += SHADER0([]() {
|
| float GetAlpha(vec2 ya_clamped) {
|
| - return alpha * TextureLookup(a_texture, ya_clamped).x;
|
| + return alpha * TextureLookupBilinear(a_texture, ya_clamped, YA).x;
|
| }
|
| });
|
| } else {
|
| @@ -2165,7 +2248,7 @@ std::string FragmentShaderYUVVideo::GetShaderString(TexCoordPrecision precision,
|
| void main() {
|
| vec2 ya_clamped =
|
| max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));
|
| - float y_raw = TextureLookup(y_texture, ya_clamped).x;
|
| + float y_raw = TextureLookupBilinear(y_texture, ya_clamped, YA).x;
|
| vec2 uv_clamped =
|
| max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));
|
| vec3 yuv = vec3(y_raw, GetUV(uv_clamped));
|
|
|