return *this;\r
}\r
\r
- shader_program(const std::string& fragment_source_str) : program_(0)\r
+ shader_program(const std::string& vertex_source_str, const std::string& fragment_source_str) : program_(0)\r
{\r
GLint success;\r
\r
try\r
{ \r
+ const char* vertex_source = vertex_source_str.c_str();\r
+ \r
+ auto vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);\r
+ \r
+ GL(glShaderSourceARB(vertex_shader, 1, &vertex_source, NULL));\r
+ GL(glCompileShaderARB(vertex_shader));\r
+\r
+ GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
+ if (success == GL_FALSE)\r
+ {\r
+ char info[2048];\r
+ GL(glGetInfoLogARB(vertex_shader, sizeof(info), 0, info));\r
+ GL(glDeleteObjectARB(vertex_shader));\r
+ std::stringstream str;\r
+ str << "Failed to compile vertex shader:" << std::endl << info << std::endl;\r
+ BOOST_THROW_EXCEPTION(common::gl::gl_error() << msg_info(str.str()));\r
+ }\r
+ \r
const char* fragment_source = fragment_source_str.c_str();\r
\r
auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);\r
}\r
\r
program_ = glCreateProgramObjectARB();\r
-\r
+ \r
+ GL(glAttachObjectARB(program_, vertex_shader));\r
GL(glAttachObjectARB(program_, fragmemt_shader));\r
\r
- GL(glDeleteObjectARB(fragmemt_shader));\r
-\r
GL(glLinkProgramARB(program_));\r
+ \r
+ GL(glDeleteObjectARB(vertex_shader));\r
+ GL(glDeleteObjectARB(fragmemt_shader));\r
\r
GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success));\r
if (success == GL_FALSE)\r
implementation(const video_format_desc& format_desc) \r
: current_(pixel_format::invalid), format_desc_(format_desc)\r
{\r
- std::string common = \r
+ std::string common_vertex = \r
"uniform sampler2D plane[4]; "\r
- "uniform vec4 plane_size[4]; "\r
+ "uniform vec4 plane_size[2]; "\r
+ " "\r
+ "void main() "\r
+ "{ "\r
+ " vec2 t0 = gl_MultiTexCoord0.xy + plane_size[0].zw*0.5; "\r
+ " vec4 x0 = vec4(-1.0, 0.0, 1.0, 2.0)*plane_size[0].z; "\r
+ " vec4 y0 = vec4(-1.0, 0.0, 1.0, 2.0)*plane_size[0].w; "\r
+ " gl_TexCoord[0] = t0.xyxy + vec4(x0.x, y0.x, x0.y, y0.y); "\r
+ " gl_TexCoord[1] = t0.xyxy + vec4(x0.z, y0.x, x0.w, y0.y); "\r
+ " gl_TexCoord[2] = t0.xyxy + vec4(x0.x, y0.z, x0.y, y0.w); "\r
+ " gl_TexCoord[3] = t0.xyxy + vec4(x0.z, y0.z, x0.w, y0.w); "\r
+ " "\r
+ " vec2 t1 = gl_MultiTexCoord0.xy + plane_size[1].zw*0.5; "\r
+ " vec4 x1 = vec4(-1.0, 0.0, 1.0, 2.0)*plane_size[1].z; "\r
+ " vec4 y1 = vec4(-1.0, 0.0, 1.0, 2.0)*plane_size[1].w; "\r
+ " gl_TexCoord[4] = t1.xyxy + vec4(x1.x, y1.x, x1.y, y1.y); "\r
+ " gl_TexCoord[5] = t1.xyxy + vec4(x1.z, y1.x, x1.w, y1.y); "\r
+ " gl_TexCoord[6] = t1.xyxy + vec4(x1.x, y1.z, x1.y, y1.w); "\r
+ " gl_TexCoord[7] = t1.xyxy + vec4(x1.z, y1.z, x1.w, y1.w); "\r
+ " "\r
+ " gl_FrontColor = gl_Color; "\r
+ " gl_Position = ftransform(); "\r
+ "} ";\r
+\r
+ std::string common_fragment = \r
+ "uniform sampler2D plane[4]; "\r
+ "uniform vec4 plane_size[2]; "\r
\r
// NOTE: YCbCr, ITU-R, http://www.intersil.com/data/an/an9717.pdf \r
// TODO: Support for more yuv formats might be needed. \r
" color.a = a; "\r
" "\r
" return color; "\r
+ "} " \r
+ " "\r
+ "vec4 texture2DNearest(sampler2D sampler, vec4 uv0, vec4 uv1, vec4 uv2, vec4 uv3, vec4 size)"\r
+ "{ "\r
+ " return texture2D(sampler, uv0.zw); "\r
+ "} "\r
+ " "\r
+ "vec4 texture2DBilinear(sampler2D sampler, vec4 uv0, vec4 uv1, vec4 uv2, vec4 uv3, vec4 size)"\r
+ "{ "\r
+ " vec2 f = fract(uv0*size.xy); "\r
+ " "\r
+ " vec4 t0 = texture2D(sampler, uv0.zw); "\r
+ " vec4 t1 = texture2D(sampler, uv1.xw); "\r
+ " vec4 t2 = texture2D(sampler, uv2.zy); "\r
+ " vec4 t3 = texture2D(sampler, uv3.xy); "\r
+ " "\r
+ " vec4 x0 = mix(t0, t1, f.x); "\r
+ " vec4 x1 = mix(t2, t3, f.x); "\r
+ " return mix(x0, x1, f.y); "\r
+ "} "\r
+ " "\r
+ "vec4 computeWeights(float x) "\r
+ "{ "\r
+ " vec4 x1 = x*vec4(1.0, 1.0, -1.0, -1.0) + vec4(1.0, 0.0, 1.0, 2.0); "\r
+ " vec4 x2 = x1*x1; "\r
+ " vec4 x3 = x2*x1; "\r
+ " "\r
+ " const float A = -0.75; " \r
+ " vec4 w; "\r
+ " w = x3 * vec2( A, A+2.0 ).xyyx; "\r
+ " w += x2 * vec2(-5.0*A, -(A+3.0)).xyyx; "\r
+ " w += x1 * vec2( 8.0*A, 0 ).xyyx; "\r
+ " w += vec2(-4.0*A, 1.0 ).xyyx; "\r
+ " return w; "\r
"} "\r
" "\r
- "vec4 texture2DBilinear(sampler2D sampler, vec2 uv, vec4 size) "\r
+ "vec4 cubicFilter(vec4 w, vec4 c0, vec4 c1, vec4 c2, vec4 c3) "\r
"{ "\r
- " vec4 x0 = texture2D(sampler, uv + size.zw * vec2(0.0, 0.0)); "\r
- " vec4 x1 = texture2D(sampler, uv + size.zw * vec2(1.0, 0.0)); "\r
- " vec4 x2 = texture2D(sampler, uv + size.zw * vec2(0.0, 1.0)); "\r
- " vec4 x3 = texture2D(sampler, uv + size.zw * vec2(1.0, 1.0)); "\r
- " vec2 f = fract(uv.xy * size.xy ); "\r
- " vec4 y0 = mix(x0, x1, f.x); "\r
- " vec4 y1 = mix(x2, x3, f.x); "\r
- " return mix(y0, y1, f.y); "\r
+ " return c0*w[0] + c1*w[1] + c2*w[2] + c3*w[3]; "\r
"} "\r
- " "\r
- "vec4 computeWeights(float x) "\r
- "{ "\r
- " vec4 x1 = x*vec4(1.0, 1.0, -1.0, -1.0) + vec4(1.0, 0.0, 1.0, 2.0); "\r
- " vec4 x2 = x1*x1; "\r
- " vec4 x3 = x2*x1; "\r
- " "\r
- " const float A = -0.75; " \r
- " vec4 w; "\r
- " w = x3 * vec2( A, A+2.0).xyyx; "\r
- " w += x2 * vec2( -5.0*A, -(A+3.0)).xyyx; "\r
- " w += x1 * vec2( 8.0*A, 0).xyyx; "\r
- " w += vec2( -4.0*A, 1.0).xyyx; "\r
- " return w; "\r
- "} "\r
- " "\r
- "vec4 cubicFilter(vec4 w, vec4 c0, vec4 c1, vec4 c2, vec4 c3) "\r
- "{ "\r
- " return c0*w[0] + c1*w[1] + c2*w[2] + c3*w[3]; "\r
- "} "\r
- " "\r
- "vec4 texture2DBicubic(sampler2D sampler, vec2 uv, vec4 size) "\r
- "{ "\r
- " vec2 f = fract(uv*size.xy); "\r
- " "\r
- " vec4 w = computeWeights(f.x); "\r
- " vec4 t0 = cubicFilter(w, texture2D(sampler, uv + vec2(-1.0, -1.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 0.0, -1.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 1.0, -1.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 2.0, -1.0) * size.zw));"\r
- " vec4 t1 = cubicFilter(w, texture2D(sampler, uv + vec2(-1.0, 0.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 0.0, 0.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 1.0, 0.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 2.0, 0.0) * size.zw));"\r
- " vec4 t2 = cubicFilter(w, texture2D(sampler, uv + vec2(-1.0, 1.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 0.0, 1.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 1.0, 1.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 2.0, 1.0) * size.zw));"\r
- " vec4 t3 = cubicFilter(w, texture2D(sampler, uv + vec2(-1.0, 2.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 0.0, 2.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 1.0, 2.0) * size.zw),"\r
- " texture2D(sampler, uv + vec2( 2.0, 2.0) * size.zw));"\r
- " "\r
- " w = computeWeights(f.y); "\r
- " return cubicFilter(w, t0, t1, t2, t3); "\r
- "} ";\r
+ " "\r
+ "vec4 texture2DBicubic(sampler2D sampler, vec4 uv0, vec4 uv1, vec4 uv2, vec4 uv3, vec4 size)"\r
+ "{ "\r
+ " vec2 f = fract(uv0*size.xy); "\r
+ " "\r
+ " vec4 w = computeWeights(f.x); "\r
+ " vec4 x0 = cubicFilter(w, texture2D(sampler, uv0.xy), "\r
+ " texture2D(sampler, uv0.zy), "\r
+ " texture2D(sampler, uv1.xy), "\r
+ " texture2D(sampler, uv1.zy)); "\r
+ " vec4 x1 = cubicFilter(w, texture2D(sampler, uv0.xw), "\r
+ " texture2D(sampler, uv0.zw), "\r
+ " texture2D(sampler, uv1.xw), "\r
+ " texture2D(sampler, uv1.zw)); "\r
+ " vec4 x2 = cubicFilter(w, texture2D(sampler, uv2.xy), "\r
+ " texture2D(sampler, uv2.zy), "\r
+ " texture2D(sampler, uv3.xy), "\r
+ " texture2D(sampler, uv3.zy)); "\r
+ " vec4 x3 = cubicFilter(w, texture2D(sampler, uv2.xw), "\r
+ " texture2D(sampler, uv2.zw), "\r
+ " texture2D(sampler, uv3.xw), "\r
+ " texture2D(sampler, uv3.zw)); "\r
+ " "\r
+ " w = computeWeights(f.y); "\r
+ " return cubicFilter(w, x0, x1, x2, x3); "\r
+ "} "; \r
\r
- shaders_[pixel_format::abgr] = common +\r
+ shaders_[pixel_format::abgr] = shader_program(common_vertex, common_fragment +\r
\r
"void main() "\r
"{ "\r
- " vec4 abgr = texture2DBicubic(plane[0], gl_TexCoord[0].st+plane_size[0].zw*0.5, plane_size[0]);"\r
- "gl_FragColor = abgr.argb * gl_Color; "\r
- "} ";\r
+ " vec4 abgr = texture2DBicubic(plane[0], gl_TexCoord[0], gl_TexCoord[1], gl_TexCoord[2], gl_TexCoord[3], plane_size[0]);"\r
+ " gl_FragColor = abgr.argb * gl_Color; "\r
+ "} ");\r
\r
- shaders_[pixel_format::argb] = common +\r
+ shaders_[pixel_format::argb]= shader_program(common_vertex, common_fragment +\r
\r
"void main() " \r
"{ "\r
- "vec4 argb = texture2DBicubic(plane[0], gl_TexCoord[0].st+plane_size[0].zw*0.5, plane_size[0]);"\r
- "gl_FragColor = argb.grab * gl_Color; " \r
- "} ";\r
+ " vec4 argb = texture2DBicubic(plane[0], gl_TexCoord[0], gl_TexCoord[1], gl_TexCoord[2], gl_TexCoord[3], plane_size[0]);"\r
+ " gl_FragColor = argb.grab * gl_Color; " \r
+ "} ");\r
\r
- shaders_[pixel_format::bgra] = common +\r
+ shaders_[pixel_format::bgra]= shader_program(common_vertex, common_fragment +\r
\r
"void main() "\r
"{ "\r
- "vec4 bgra = texture2DBicubic(plane[0], gl_TexCoord[0].st+plane_size[0].zw*0.5, plane_size[0]);"\r
- "gl_FragColor = bgra.rgba * gl_Color; "\r
- "} ";\r
+ " vec4 bgra = texture2DBicubic(plane[0], gl_TexCoord[0], gl_TexCoord[1], gl_TexCoord[2], gl_TexCoord[3], plane_size[0]);"\r
+ " gl_FragColor = bgra.rgba * gl_Color; "\r
+ "} ");\r
\r
- shaders_[pixel_format::rgba] = common +\r
+ shaders_[pixel_format::rgba] = shader_program(common_vertex, common_fragment +\r
\r
"void main() "\r
"{ "\r
- "vec4 rgba = texture2DBicubic(plane[0], gl_TexCoord[0].st+plane_size[0].zw*0.5, plane_size[0]);"\r
- "gl_FragColor = rgba.bgra * gl_Color; "\r
- "} ";\r
+ " vec4 rgba = texture2DBicubic(plane[0], gl_TexCoord[0], gl_TexCoord[1], gl_TexCoord[2], gl_TexCoord[3], plane_size[0]);"\r
+ " gl_FragColor = rgba.bgra * gl_Color; "\r
+ "} ");\r
\r
- shaders_[pixel_format::ycbcr] = common +\r
+ shaders_[pixel_format::ycbcr] = shader_program(common_vertex, common_fragment +\r
\r
"void main() "\r
"{ "\r
- "float y = texture2DBicubic(plane[0], gl_TexCoord[0].st+plane_size[0].zw*0.5, plane_size[0]).r;"\r
- "float cb = texture2DBicubic(plane[1], gl_TexCoord[0].st+plane_size[1].zw*0.5, plane_size[1]).r;"\r
- "float cr = texture2DBicubic(plane[2], gl_TexCoord[0].st+plane_size[2].zw*0.5, plane_size[2]).r;"\r
- "float a = 1.0; " \r
- "gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color; "\r
- "} ";\r
+ " float y = texture2DBicubic(plane[0], gl_TexCoord[0], gl_TexCoord[1], gl_TexCoord[2], gl_TexCoord[3], plane_size[0]).r;"\r
+ " float cb = texture2DBicubic(plane[1], gl_TexCoord[4], gl_TexCoord[5], gl_TexCoord[6], gl_TexCoord[7], plane_size[1]).r;"\r
+ " float cr = texture2DBicubic(plane[2], gl_TexCoord[4], gl_TexCoord[5], gl_TexCoord[6], gl_TexCoord[7], plane_size[1]).r;"\r
+ " float a = 1.0; " \r
+ " gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color; "\r
+ "} ");\r
\r
- shaders_[pixel_format::ycbcra] = common +\r
+ shaders_[pixel_format::ycbcra] = shader_program(common_vertex, common_fragment +\r
\r
"void main() "\r
"{ "\r
- "float y = texture2DBicubic(plane[0], gl_TexCoord[0].st+plane_size[0].zw*0.5, plane_size[0]).r;"\r
- "float cb = texture2DBicubic(plane[1], gl_TexCoord[0].st+plane_size[1].zw*0.5, plane_size[1]).r;"\r
- "float cr = texture2DBicubic(plane[2], gl_TexCoord[0].st+plane_size[2].zw*0.5, plane_size[2]).r;"\r
- "float a = texture2DBicubic(plane[3], gl_TexCoord[0].st+plane_size[3].zw*0.5, plane_size[3]).r;"\r
- "gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color; "\r
- "} ";\r
+ " float y = texture2DBicubic(plane[0], gl_TexCoord[0], gl_TexCoord[1], gl_TexCoord[2], gl_TexCoord[3], plane_size[0]).r;"\r
+ " float cb = texture2DBicubic(plane[1], gl_TexCoord[4], gl_TexCoord[5], gl_TexCoord[6], gl_TexCoord[7], plane_size[1]).r;"\r
+ " float cr = texture2DBicubic(plane[2], gl_TexCoord[4], gl_TexCoord[5], gl_TexCoord[6], gl_TexCoord[7], plane_size[1]).r;"\r
+ " float a = texture2DBicubic(plane[3], gl_TexCoord[0], gl_TexCoord[1], gl_TexCoord[2], gl_TexCoord[3], plane_size[0]).r;"\r
+ " gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color; "\r
+ "} ");\r
}\r
\r
void use(const pixel_format_desc& desc)\r
\r
void set_planes(const std::vector<pixel_format_desc::plane>& planes)\r
{\r
- for(size_t n = 0; n < planes.size(); ++n)\r
+ for(size_t n = 0; n < planes.size() && n < 2; ++n)\r
glUniform4f(glGetUniformLocation(shaders_[current_].program(), std::string("plane_size[" + boost::lexical_cast<std::string>(n) + "]").c_str()), \r
static_cast<float>(planes[n].width), static_cast<float>(planes[n].height), 1.0f/static_cast<float>(planes[n].width), 1.0f/static_cast<float>(planes[n].height));\r
}\r