1 #include "../StdAfx.h"
\r
3 #include "gpu_frame_transform.h"
\r
5 #include "../../common/exception/exceptions.h"
\r
6 #include "../../common/gl/gl_check.h"
\r
11 #include <unordered_map>
\r
13 namespace caspar { namespace core {
\r
15 class shader_program
\r
18 shader_program(const std::string& fragment_source_str)
\r
22 const char* fragment_source = fragment_source_str.c_str();
\r
23 static const char* vertex_source =
\r
26 "gl_TexCoord[0] = gl_MultiTexCoord0;"
\r
27 "gl_FrontColor = gl_Color;"
\r
28 "gl_Position = ftransform();"
\r
31 program_ = glCreateProgramObjectARB();
\r
33 auto vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
\r
34 auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
\r
36 GL(glShaderSourceARB(vertex_shader, 1, &vertex_source, NULL));
\r
37 GL(glShaderSourceARB(fragmemt_shader, 1, &fragment_source, NULL));
\r
38 GL(glCompileShaderARB(vertex_shader));
\r
39 GL(glCompileShaderARB(fragmemt_shader));
\r
42 GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));
\r
43 if (success == GL_FALSE)
\r
46 GL(glGetInfoLogARB(vertex_shader, sizeof(log), 0, log));
\r
47 GL(glDeleteObjectARB(vertex_shader));
\r
48 GL(glDeleteObjectARB(fragmemt_shader));
\r
49 GL(glDeleteObjectARB(program_));
\r
50 std::stringstream str;
\r
51 str << "Failed to compile vertex shader:" << std::endl << log << std::endl;
\r
52 BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));
\r
54 GL(glGetObjectParameterivARB(fragmemt_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));
\r
55 if (success == GL_FALSE)
\r
58 GL(glGetInfoLogARB(fragmemt_shader, sizeof(log), 0, log));
\r
59 GL(glDeleteObjectARB(vertex_shader));
\r
60 GL(glDeleteObjectARB(fragmemt_shader));
\r
61 GL(glDeleteObjectARB(program_));
\r
62 std::stringstream str;
\r
63 str << "Failed to compile fragment shader:" << std::endl << log << std::endl;
\r
64 BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));
\r
67 GL(glAttachObjectARB(program_, vertex_shader));
\r
68 GL(glAttachObjectARB(program_, fragmemt_shader));
\r
70 GL(glDeleteObjectARB(vertex_shader));
\r
71 GL(glDeleteObjectARB(fragmemt_shader));
\r
73 GL(glLinkProgramARB(program_));
\r
75 GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success));
\r
76 if (success == GL_FALSE)
\r
79 GL(glGetInfoLogARB(program_, sizeof(log), 0, log));
\r
80 CASPAR_LOG(warning) << "Failed to link shader:" << std::endl
\r
81 << log << std::endl;
\r
82 GL(glDeleteObjectARB(program_));
\r
83 BOOST_THROW_EXCEPTION(caspar_exception());
\r
85 GL(glUseProgramObjectARB(program_));
\r
86 glUniform1i(glGetUniformLocation(program_, "tex0"), 0);
\r
87 glUniform1i(glGetUniformLocation(program_, "tex1"), 1);
\r
88 glUniform1i(glGetUniformLocation(program_, "tex2"), 2);
\r
89 glUniform1i(glGetUniformLocation(program_, "tex3"), 3);
\r
93 CASPAR_LOG_CURRENT_EXCEPTION();
\r
100 GL(glUseProgramObjectARB(program_));
\r
106 typedef std::shared_ptr<shader_program> shader_program_ptr;
\r
108 struct gpu_frame_transform::implementation
\r
110 implementation() : current_(pixel_format::invalid_pixel_format)
\r
112 std::string common =
\r
113 "uniform sampler2D tex0;"
\r
114 "uniform sampler2D tex1;"
\r
115 "uniform sampler2D tex2;"
\r
116 "uniform sampler2D tex3;"
\r
118 "vec4 yuva_to_bgra(float y, float u, float v, float a)"
\r
125 "color.r = clamp(y + 1.370705 * v, 0.0 , 1.0);"
\r
126 "color.g = clamp(y - 0.698001 * v - 0.337633 * u, 0.0 , 1.0);"
\r
127 "color.b = clamp(y + 1.732446 * u, 0.0 , 1.0);"
\r
133 shaders_[pixel_format::abgr] = std::make_shared<shader_program>
\r
139 "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).argb * gl_Color;"
\r
142 shaders_[pixel_format::argb] = std::make_shared<shader_program>
\r
148 "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).grab * gl_Color;"
\r
151 shaders_[pixel_format::bgra] = std::make_shared<shader_program>
\r
157 "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).rgba * gl_Color;"
\r
160 shaders_[pixel_format::rgba] = std::make_shared<shader_program>
\r
166 "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).bgra * gl_Color;"
\r
169 shaders_[pixel_format::yuv] = std::make_shared<shader_program>
\r
175 "float y = texture2D(tex0, gl_TexCoord[0].st).r;"
\r
176 "float u = texture2D(tex1, gl_TexCoord[0].st).r;"
\r
177 "float v = texture2D(tex2, gl_TexCoord[0].st).r;"
\r
178 "gl_FragColor = yuva_to_bgra(y, u , v, 1.0) * gl_Color;"
\r
181 shaders_[pixel_format::yuva] = std::make_shared<shader_program>
\r
187 "float y = texture2D(tex0, gl_TexCoord[0].st).r;"
\r
188 "float u = texture2D(tex1, gl_TexCoord[0].st).r;"
\r
189 "float v = texture2D(tex2, gl_TexCoord[0].st).r;"
\r
190 "float a = texture2D(tex3, gl_TexCoord[0].st).r;"
\r
191 "gl_FragColor = yuva_to_bgra(y, u, v, a) * gl_Color;"
\r
196 void set_pixel_format(pixel_format format)
\r
198 if(current_ == format)
\r
201 shaders_[format]->use();
\r
204 pixel_format current_;
\r
205 std::map<pixel_format, shader_program_ptr> shaders_;
\r
208 gpu_frame_transform::gpu_frame_transform() : impl_(new implementation()){}
\r
209 void gpu_frame_transform::set_pixel_format(pixel_format format){impl_->set_pixel_format(format);}
\r