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) { |