]> git.sesse.net Git - casparcg/blob - core/frame/gpu_frame_transform.cpp
2.0.0.2:
[casparcg] / core / frame / gpu_frame_transform.cpp
1 #include "../StdAfx.h"\r
2 \r
3 #include "gpu_frame_transform.h"\r
4 \r
5 #include "../../common/exception/exceptions.h"\r
6 #include "../../common/gl/gl_check.h"\r
7 \r
8 #include <Glee.h>\r
9 \r
10 #include <fstream>\r
11 #include <unordered_map>\r
12 \r
13 namespace caspar { namespace core {\r
14         \r
15 class shader_program\r
16 {\r
17 public:\r
18         shader_program(const std::string& fragment_source_str)\r
19         {\r
20                 try\r
21                 {               \r
22                         const char* fragment_source = fragment_source_str.c_str();\r
23                         static const char* vertex_source = \r
24                                 "void main()"\r
25                                 "{"\r
26                                         "gl_TexCoord[0] = gl_MultiTexCoord0;"\r
27                                         "gl_FrontColor = gl_Color;"\r
28                                         "gl_Position = ftransform();"\r
29                                 "}";\r
30 \r
31                         program_ = glCreateProgramObjectARB();\r
32 \r
33                         auto vertex_shader   = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);\r
34                         auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);\r
35 \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
40 \r
41                         GLint success;\r
42                         GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
43                         if (success == GL_FALSE)\r
44                         {\r
45                                 char log[1024];\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
53                         }\r
54                         GL(glGetObjectParameterivARB(fragmemt_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
55                         if (success == GL_FALSE)\r
56                         {\r
57                                 char log[1024];\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
65                         }\r
66 \r
67                         GL(glAttachObjectARB(program_, vertex_shader));\r
68                         GL(glAttachObjectARB(program_, fragmemt_shader));\r
69 \r
70                         GL(glDeleteObjectARB(vertex_shader));\r
71                         GL(glDeleteObjectARB(fragmemt_shader));\r
72 \r
73                         GL(glLinkProgramARB(program_));\r
74 \r
75                         GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success));\r
76                         if (success == GL_FALSE)\r
77                         {\r
78                                 char log[1024];\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
84                         }\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
90                 }\r
91                 catch(...)\r
92                 {\r
93                         CASPAR_LOG_CURRENT_EXCEPTION();\r
94                         throw;\r
95                 }\r
96         }\r
97 \r
98         void use()\r
99         {\r
100                 GL(glUseProgramObjectARB(program_));\r
101         }\r
102 \r
103 private:\r
104         GLuint program_;\r
105 };\r
106 typedef std::shared_ptr<shader_program> shader_program_ptr;\r
107 \r
108 struct gpu_frame_transform::implementation\r
109 {\r
110         implementation() : current_(pixel_format::invalid_pixel_format)\r
111         {\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
117 \r
118                         "vec4 yuva_to_bgra(float y, float u, float v, float a)"\r
119                         "{"\r
120                            "vec4 color;"\r
121    \r
122                            "u -= 0.5;"\r
123                            "v -= 0.5;"\r
124 \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
128                            "color.a = a;"\r
129 \r
130                           " return color;"\r
131                         "}";\r
132 \r
133                 shaders_[pixel_format::abgr] = std::make_shared<shader_program>\r
134                 (\r
135                         common +\r
136 \r
137                         "void main()"\r
138                         "{"\r
139                                 "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).argb * gl_Color;"\r
140                         "}"\r
141                 );\r
142                 shaders_[pixel_format::argb] = std::make_shared<shader_program>\r
143                 (\r
144                         common +\r
145 \r
146                         "void main()"\r
147                         "{"\r
148                                 "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).grab * gl_Color;"\r
149                         "}"\r
150                 );\r
151                 shaders_[pixel_format::bgra] = std::make_shared<shader_program>\r
152                 (\r
153                         common +\r
154 \r
155                         "void main()"\r
156                         "{"\r
157                                 "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).rgba * gl_Color;"\r
158                         "}"\r
159                 );\r
160                 shaders_[pixel_format::rgba] = std::make_shared<shader_program>\r
161                 (\r
162                         common +\r
163 \r
164                         "void main()"\r
165                         "{"\r
166                                 "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).bgra * gl_Color;"\r
167                         "}"\r
168                 );\r
169                 shaders_[pixel_format::yuv] = std::make_shared<shader_program>\r
170                 (\r
171                         common +\r
172 \r
173                         "void main()"\r
174                         "{"\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
179                         "}"\r
180                 );\r
181                 shaders_[pixel_format::yuva] = std::make_shared<shader_program>\r
182                 (\r
183                         common +\r
184 \r
185                         "void main()"\r
186                         "{"\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
192                         "}"\r
193                 );\r
194         }\r
195 \r
196         void set_pixel_format(pixel_format format)\r
197         {\r
198                 if(current_ == format)\r
199                         return;\r
200                 current_ = format;\r
201                 shaders_[format]->use();\r
202         }\r
203 \r
204         pixel_format current_;\r
205         std::map<pixel_format, shader_program_ptr> shaders_;\r
206 };\r
207 \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
210 \r
211 }}