Chromium Code Reviews| Index: cc/output/shader.cc |
| diff --git a/cc/output/shader.cc b/cc/output/shader.cc |
| index 9b54c544e4894cecd83ca73afbfd417b5aff7940..8a17e36022520448c7c4c8995a15dc704d697cbd 100644 |
| --- a/cc/output/shader.cc |
| +++ b/cc/output/shader.cc |
| @@ -2019,24 +2019,41 @@ FragmentShaderYUVVideo::FragmentShaderYUVVideo() |
| v_texture_location_(-1), |
| uv_texture_location_(-1), |
| a_texture_location_(-1), |
| + lut_texture_location_(-1), |
| alpha_location_(-1), |
| yuv_matrix_location_(-1), |
| yuv_adj_location_(-1), |
| ya_clamp_rect_location_(-1), |
| - uv_clamp_rect_location_(-1) {} |
| + uv_clamp_rect_location_(-1), |
| + resource_multiplier_location_(-1), |
| + resource_offset_location_(-1) {} |
| void FragmentShaderYUVVideo::SetFeatures(bool use_alpha_texture, |
| - bool use_nv12) { |
| + bool use_nv12, |
| + bool use_color_lut) { |
| use_alpha_texture_ = use_alpha_texture; |
| use_nv12_ = use_nv12; |
| + use_color_lut_ = use_color_lut; |
| } |
| void FragmentShaderYUVVideo::Init(GLES2Interface* context, |
| unsigned program, |
| int* base_uniform_index) { |
| static const char* uniforms[] = { |
| - "y_texture", "u_texture", "v_texture", "uv_texture", "a_texture", |
| - "alpha", "yuv_matrix", "yuv_adj", "ya_clamp_rect", "uv_clamp_rect"}; |
| + "y_texture", |
| + "u_texture", |
| + "v_texture", |
| + "uv_texture", |
| + "a_texture", |
| + "lut_texture", |
| + "resource_multiplier", |
| + "resource_offset", |
| + "yuv_matrix", |
| + "yuv_adj", |
| + "alpha", |
| + "ya_clamp_rect", |
| + "uv_clamp_rect", |
| + }; |
| int locations[arraysize(uniforms)]; |
| GetProgramUniformLocations(context, |
| @@ -2046,15 +2063,26 @@ void FragmentShaderYUVVideo::Init(GLES2Interface* context, |
| locations, |
| base_uniform_index); |
| y_texture_location_ = locations[0]; |
| - u_texture_location_ = locations[1]; |
| - v_texture_location_ = locations[2]; |
| - uv_texture_location_ = locations[3]; |
| - a_texture_location_ = locations[4]; |
| - alpha_location_ = locations[5]; |
| - yuv_matrix_location_ = locations[6]; |
| - yuv_adj_location_ = locations[7]; |
| - ya_clamp_rect_location_ = locations[8]; |
| - uv_clamp_rect_location_ = locations[9]; |
| + if (!use_nv12_) { |
| + u_texture_location_ = locations[1]; |
| + v_texture_location_ = locations[2]; |
| + } else { |
| + uv_texture_location_ = locations[3]; |
| + } |
| + if (use_alpha_texture_) { |
| + a_texture_location_ = locations[4]; |
| + } |
| + if (use_color_lut_) { |
| + lut_texture_location_ = locations[5]; |
| + resource_multiplier_location_ = locations[6]; |
| + resource_offset_location_ = locations[7]; |
| + } else { |
| + 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]; |
| } |
| std::string FragmentShaderYUVVideo::GetShaderString(TexCoordPrecision precision, |
| @@ -2066,44 +2094,22 @@ std::string FragmentShaderYUVVideo::GetShaderString(TexCoordPrecision precision, |
| varying TexCoordPrecision vec2 v_uvTexCoord; |
| uniform SamplerType y_texture; |
| uniform float alpha; |
| - uniform vec3 yuv_adj; |
| - uniform mat3 yuv_matrix; |
| uniform vec4 ya_clamp_rect; |
| uniform vec4 uv_clamp_rect; |
| }); |
| - if (use_nv12_) { |
| - head += " uniform SamplerType uv_texture;\n"; |
| - } else { |
| - head += " uniform SamplerType u_texture;\n"; |
| - head += " uniform SamplerType v_texture;\n"; |
| - } |
| - if (use_alpha_texture_) { |
| - head += " uniform SamplerType a_texture;\n"; |
| - } |
| - std::string main = SHADER0([]() { |
| - 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; |
| - vec2 uv_clamped = |
| - max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord)); |
| - vec2 uv_unsigned = GetUV(uv_clamped); |
| - vec3 yuv = vec3(y_raw, uv_unsigned) + yuv_adj; |
| - vec3 rgb = yuv_matrix * yuv; |
| - gl_FragColor = vec4(rgb, 1.0) * GetAlpha(ya_clamped); |
| - } |
| - }); |
| - |
| - std::string get_uv; |
| + std::string functions = ""; |
| if (use_nv12_) { |
| - get_uv = SHADER0([]() { |
| + head += " uniform SamplerType uv_texture;\n"; |
| + functions += SHADER0([]() { |
| vec2 GetUV(vec2 uv_clamped) { |
| return TextureLookup(uv_texture, uv_clamped).xy; |
| } |
| }); |
| } else { |
| - get_uv = SHADER0([]() { |
| + head += " uniform SamplerType u_texture;\n"; |
| + 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); |
| @@ -2111,20 +2117,63 @@ std::string FragmentShaderYUVVideo::GetShaderString(TexCoordPrecision precision, |
| }); |
| } |
| - std::string get_alpha; |
| if (use_alpha_texture_) { |
| - get_alpha = SHADER0([]() { |
| + head += " uniform SamplerType a_texture;\n"; |
| + functions += SHADER0([]() { |
| float GetAlpha(vec2 ya_clamped) { |
| return alpha * TextureLookup(a_texture, ya_clamped).x; |
| } |
| }); |
| } else { |
| - get_alpha = SHADER0([]() { |
| + functions += SHADER0([]() { |
| float GetAlpha(vec2 ya_clamped) { return alpha; } |
| }); |
| } |
| - return FRAGMENT_SHADER(head, get_uv + get_alpha + main); |
| + if (use_color_lut_) { |
| + head += " uniform sampler2D lut_texture;\n"; |
| + head += " uniform float resource_multiplier;\n"; |
| + head += " uniform float resource_offset;\n"; |
| + functions += SHADER0([]() { |
| + vec4 LUT(sampler2D sampler, vec3 pos, float size) { |
|
ccameron
2016/08/08 18:45:07
With sampler3D, this just becomes texture3D(sample
hubbe
2016/08/08 19:45:38
Agreed, but it's a performance minefield...
textur
|
| + pos *= size - 1.0; |
| + // Select layer |
| + float layer = min(floor(pos.x), size - 2.0); |
| + // Compress the yz coordinates so they stay within |
| + // [0.5 .. 31.5] / 32 (assuming a LUT size of 32^3) |
| + pos.yz = (pos.yz + vec2(0.5)) / size; |
| + pos.z = (pos.z + layer) / size; |
| + return mix(texture2D(sampler, pos.yz), |
| + texture2D(sampler, pos.yz + vec2(0, 1.0 / size)), |
| + pos.x - layer); |
| + } |
| + |
| + vec3 yuv2rgb(vec3 yuv) { |
| + yuv = yuv * resource_multiplier - vec3(resource_offset); |
| + return LUT(lut_texture, yuv, 32.0).xyz; |
| + } |
| + }); |
| + } else { |
| + head += " uniform mat3 yuv_matrix;\n"; |
| + head += " uniform vec3 yuv_adj;\n"; |
| + functions += SHADER0([]() { |
| + vec3 yuv2rgb(vec3 yuv) { return yuv_matrix * (yuv + yuv_adj); } |
| + }); |
| + } |
| + |
| + functions += SHADER0([]() { |
| + 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; |
| + vec2 uv_clamped = |
| + max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord)); |
| + vec3 yuv = vec3(y_raw, GetUV(uv_clamped)); |
| + gl_FragColor = vec4(yuv2rgb(yuv), 1.0) * GetAlpha(ya_clamped); |
| + } |
| + }); |
| + |
| + return FRAGMENT_SHADER(head, functions); |
| } |
| FragmentShaderColor::FragmentShaderColor() : color_location_(-1) { |