]> git.sesse.net Git - casparcg/blob - core/mixer/image/image_kernel.cpp
2.0. image_kernel: Don't render fully transparent frames.
[casparcg] / core / mixer / image / image_kernel.cpp
1 /*\r
2 * copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 *  This file is part of CasparCG.\r
5 *\r
6 *    CasparCG is free software: you can redistribute it and/or modify\r
7 *    it under the terms of the GNU General Public License as published by\r
8 *    the Free Software Foundation, either version 3 of the License, or\r
9 *    (at your option) any later version.\r
10 *\r
11 *    CasparCG is distributed in the hope that it will be useful,\r
12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 *    GNU General Public License for more details.\r
15 \r
16 *    You should have received a copy of the GNU General Public License\r
17 *    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 */\r
20 #include "../../stdafx.h"\r
21 \r
22 #include "image_kernel.h"\r
23 \r
24 #include <common/exception/exceptions.h>\r
25 #include <common/gl/gl_check.h>\r
26 \r
27 #include <core/video_format.h>\r
28 #include <core/producer/frame/pixel_format.h>\r
29 #include <core/producer/frame/image_transform.h>\r
30 \r
31 #include <boost/noncopyable.hpp>\r
32 \r
33 #include <unordered_map>\r
34 \r
35 namespace caspar { namespace core {\r
36 \r
37 class shader_program : boost::noncopyable\r
38 {\r
39         GLuint program_;\r
40 public:\r
41 \r
42         shader_program() : program_(0) {}\r
43         shader_program(shader_program&& other) : program_(other.program_){other.program_ = 0;}\r
44         shader_program(const std::string& vertex_source_str, const std::string& fragment_source_str) : program_(0)\r
45         {\r
46                 GLint success;\r
47         \r
48                 const char* vertex_source = vertex_source_str.c_str();\r
49                                                 \r
50                 auto vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);\r
51                                         \r
52                 GL(glShaderSourceARB(vertex_shader, 1, &vertex_source, NULL));\r
53                 GL(glCompileShaderARB(vertex_shader));\r
54 \r
55                 GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
56                 if (success == GL_FALSE)\r
57                 {\r
58                         char info[2048];\r
59                         GL(glGetInfoLogARB(vertex_shader, sizeof(info), 0, info));\r
60                         GL(glDeleteObjectARB(vertex_shader));\r
61                         std::stringstream str;\r
62                         str << "Failed to compile vertex shader:" << std::endl << info << std::endl;\r
63                         BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
64                 }\r
65                         \r
66                 const char* fragment_source = fragment_source_str.c_str();\r
67                                                 \r
68                 auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);\r
69                                         \r
70                 GL(glShaderSourceARB(fragmemt_shader, 1, &fragment_source, NULL));\r
71                 GL(glCompileShaderARB(fragmemt_shader));\r
72 \r
73                 GL(glGetObjectParameterivARB(fragmemt_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
74                 if (success == GL_FALSE)\r
75                 {\r
76                         char info[2048];\r
77                         GL(glGetInfoLogARB(fragmemt_shader, sizeof(info), 0, info));\r
78                         GL(glDeleteObjectARB(fragmemt_shader));\r
79                         std::stringstream str;\r
80                         str << "Failed to compile fragment shader:" << std::endl << info << std::endl;\r
81                         BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
82                 }\r
83                         \r
84                 program_ = glCreateProgramObjectARB();\r
85                         \r
86                 GL(glAttachObjectARB(program_, vertex_shader));\r
87                 GL(glAttachObjectARB(program_, fragmemt_shader));\r
88 \r
89                 GL(glLinkProgramARB(program_));\r
90                         \r
91                 GL(glDeleteObjectARB(vertex_shader));\r
92                 GL(glDeleteObjectARB(fragmemt_shader));\r
93 \r
94                 GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success));\r
95                 if (success == GL_FALSE)\r
96                 {\r
97                         char info[2048];\r
98                         GL(glGetInfoLogARB(program_, sizeof(info), 0, info));\r
99                         GL(glDeleteObjectARB(program_));\r
100                         std::stringstream str;\r
101                         str << "Failed to link shader program:" << std::endl << info << std::endl;\r
102                         BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
103                 }\r
104                 GL(glUseProgramObjectARB(program_));\r
105                 glUniform1i(glGetUniformLocation(program_, "plane[0]"), 0);\r
106                 glUniform1i(glGetUniformLocation(program_, "plane[1]"), 1);\r
107                 glUniform1i(glGetUniformLocation(program_, "plane[2]"), 2);\r
108                 glUniform1i(glGetUniformLocation(program_, "plane[3]"), 3);\r
109                 glUniform1i(glGetUniformLocation(program_, "plane[4]"), 4);\r
110         }\r
111 \r
112         GLint get_location(const char* name)\r
113         {\r
114                 GLint loc = glGetUniformLocation(program_, name);\r
115                 return loc;\r
116         }\r
117 \r
118         shader_program& operator=(shader_program&& other) \r
119         {\r
120                 program_ = other.program_; \r
121                 other.program_ = 0; \r
122                 return *this;\r
123         }\r
124 \r
125         ~shader_program()\r
126         {\r
127                 glDeleteProgram(program_);\r
128         }\r
129 \r
130         void use()\r
131         {       \r
132                 GL(glUseProgramObjectARB(program_));            \r
133         }\r
134 };\r
135 \r
136 GLubyte progressive_pattern[] = {\r
137         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
138         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
139         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
140         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xFF, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
141         \r
142 GLubyte upper_pattern[] = {\r
143         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
144         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
145         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
146         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};\r
147                 \r
148 GLubyte lower_pattern[] = {\r
149         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \r
150         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
151         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
152         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};\r
153 \r
154 struct image_kernel::implementation : boost::noncopyable\r
155 {       \r
156         std::unordered_map<core::pixel_format::type, shader_program> shaders_;\r
157 \r
158 public:\r
159         std::unordered_map<core::pixel_format::type, shader_program>& shaders()\r
160         {\r
161                 GL(glEnable(GL_POLYGON_STIPPLE));\r
162                 GL(glEnable(GL_BLEND));\r
163                 GL(glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE));\r
164 \r
165                 if(shaders_.empty())\r
166                 {\r
167                 std::string common_vertex = \r
168                         "void main()                                                                                                                    "\r
169                         "{                                                                                                                                              "\r
170                         "       gl_TexCoord[0] = gl_MultiTexCoord0;                                                                     "\r
171                         "       gl_TexCoord[1] = gl_MultiTexCoord1;                                                                     "\r
172                         "       gl_FrontColor = gl_Color;                                                                                       "\r
173                         "       gl_Position = ftransform();                                                                                     "\r
174                         "}                                                                                                                                              ";\r
175 \r
176                 std::string common_fragment = \r
177                         "uniform sampler2D      plane[5];                                                                                       "\r
178                         "uniform float          gain;                                                                                           "\r
179                         "uniform bool           HD;                                                                                                     "\r
180                         "uniform bool           local_key;                                                                                      "\r
181                         "uniform bool           layer_key;                                                                                      "\r
182                                                                                                                                                                 \r
183                         // NOTE: YCbCr, ITU-R, http://www.intersil.com/data/an/an9717.pdf               \r
184                         // TODO: Support for more yuv formats might be needed.                                  \r
185                         "vec4 ycbcra_to_bgra_sd(float y, float cb, float cr, float a)                   "\r
186                         "{                                                                                                                                              "\r
187                         "       cb -= 0.5;                                                                                                                      "\r
188                         "       cr -= 0.5;                                                                                                                      "\r
189                         "       y = 1.164*(y-0.0625);                                                                                           "\r
190                         "                                                                                                                                               "\r
191                         "       vec4 color;                                                                                                                     "\r
192                         "       color.r = y + 1.596 * cr;                                                                                       "\r
193                         "       color.g = y - 0.813 * cr - 0.391 * cb;                                                          "\r
194                         "       color.b = y + 2.018 * cb;                                                                                       "\r
195                         "       color.a = a;                                                                                                            "\r
196                         "                                                                                                                                               "\r
197                         "       return color;                                                                                                           "\r
198                         "}                                                                                                                                              "                       \r
199                         "                                                                                                                                               "\r
200 \r
201                         "vec4 ycbcra_to_bgra_hd(float y, float cb, float cr, float a)                   "\r
202                         "{                                                                                                                                              "\r
203                         "       cb -= 0.5;                                                                                                                      "\r
204                         "       cr -= 0.5;                                                                                                                      "\r
205                         "       y = 1.164*(y-0.0625);                                                                                           "\r
206                         "                                                                                                                                               "\r
207                         "       vec4 color;                                                                                                                     "\r
208                         "       color.r = y + 1.793 * cr;                                                                                       "\r
209                         "       color.g = y - 0.534 * cr - 0.213 * cb;                                                          "\r
210                         "       color.b = y + 2.115 * cb;                                                                                       "\r
211                         "       color.a = a;                                                                                                            "\r
212                         "                                                                                                                                               "\r
213                         "       return color;                                                                                                           "\r
214                         "}                                                                                                                                              "                       \r
215                         "                                                                                                                                               ";\r
216                         \r
217                 shaders_[core::pixel_format::gray] = shader_program(common_vertex, common_fragment +\r
218 \r
219                         "void main()                                                                                                                    "\r
220                         "{                                                                                                                                              "\r
221                         "       vec4 rgba = vec4(texture2D(plane[0], gl_TexCoord[0].st).rrr, 1.0);      "\r
222                         "       if(local_key)                                                                                                           "\r
223                         "               rgba.a = texture2D(plane[3], gl_TexCoord[1].st).r;                              "\r
224                         "       if(layer_key)                                                                                                           "\r
225                         "               rgba.a *= texture2D(plane[4], gl_TexCoord[1].st).r;                             "\r
226                         "       gl_FragColor = rgba * gain;                                                                                     "\r
227                         "}                                                                                                                                              ");\r
228 \r
229                 shaders_[core::pixel_format::abgr] = shader_program(common_vertex, common_fragment +\r
230 \r
231                         "void main()                                                                                                                    "\r
232                         "{                                                                                                                                              "\r
233                         "       vec4 abgr = texture2D(plane[0], gl_TexCoord[0].st);                                     "\r
234                         "       if(local_key)                                                                                                           "\r
235                         "               abgr.b = texture2D(plane[3], gl_TexCoord[1].st).r;                              "\r
236                         "       if(layer_key)                                                                                                           "\r
237                         "               abgr.b *= texture2D(plane[4], gl_TexCoord[1].st).r;                             "\r
238                         "       gl_FragColor = abgr.argb * gain;                                                                        "\r
239                         "}                                                                                                                                              ");\r
240                 \r
241                 shaders_[core::pixel_format::argb]= shader_program(common_vertex, common_fragment +\r
242 \r
243                         "void main()                                                                                                                    "       \r
244                         "{                                                                                                                                              "\r
245                         "       vec4 argb = texture2D(plane[0], gl_TexCoord[0].st);                                     "\r
246                         "       if(local_key)                                                                                                           "\r
247                         "               argb.b = texture2D(plane[3], gl_TexCoord[1].st).r;                              "\r
248                         "       if(layer_key)                                                                                                           "\r
249                         "               argb.b *= texture2D(plane[4], gl_TexCoord[1].st).r;                             "\r
250                         "       gl_FragColor = argb.grab * gl_Color * gain;                                                     "\r
251                         "}                                                                                                                                              ");\r
252                 \r
253                 shaders_[core::pixel_format::bgra]= shader_program(common_vertex, common_fragment +\r
254 \r
255                         "void main()                                                                                                                    "\r
256                         "{                                                                                                                                              "\r
257                         "       vec4 bgra = texture2D(plane[0], gl_TexCoord[0].st);                                     "\r
258                         "       if(local_key)                                                                                                           "\r
259                         "               bgra.a = texture2D(plane[3], gl_TexCoord[1].st).r;                              "\r
260                         "       if(layer_key)                                                                                                           "\r
261                         "               bgra.a *= texture2D(plane[4], gl_TexCoord[1].st).r;                             "\r
262                         "       gl_FragColor = bgra.rgba * gl_Color * gain;                                                     "\r
263                         "}                                                                                                                                              ");\r
264                 \r
265                 shaders_[core::pixel_format::rgba] = shader_program(common_vertex, common_fragment +\r
266 \r
267                         "void main()                                                                                                                    "\r
268                         "{                                                                                                                                              "\r
269                         "       vec4 rgba = texture2D(plane[0], gl_TexCoord[0].st);                                     "\r
270                         "       if(local_key)                                                                                                           "\r
271                         "               rgba.a = texture2D(plane[3], gl_TexCoord[1].st).r;                              "\r
272                         "       if(layer_key)                                                                                                           "\r
273                         "               rgba.a *= texture2D(plane[4], gl_TexCoord[1].st).r;                             "\r
274                         "       gl_FragColor = rgba.bgra * gl_Color * gain;                                                     "\r
275                         "}                                                                                                                                              ");\r
276                 \r
277                 shaders_[core::pixel_format::ycbcr] = shader_program(common_vertex, common_fragment +\r
278 \r
279                         "void main()                                                                                                                    "\r
280                         "{                                                                                                                                              "\r
281                         "       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;                            "\r
282                         "       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;                            "\r
283                         "       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;                            "\r
284                         "       float a = 1.0;                                                                                                          "       \r
285                         "       if(local_key)                                                                                                           "\r
286                         "               a = texture2D(plane[3], gl_TexCoord[1].st).r;                                   "\r
287                         "       if(layer_key)                                                                                                           "\r
288                         "               a *= texture2D(plane[4], gl_TexCoord[1].st).r;                                  "\r
289                         "       if(HD)                                                                                                                          "\r
290                         "               gl_FragColor = ycbcra_to_bgra_hd(y, cb, cr, a) * gl_Color * gain;"\r
291                         "       else                                                                                                                            "\r
292                         "               gl_FragColor = ycbcra_to_bgra_sd(y, cb, cr, a) * gl_Color * gain;"\r
293                         "}                                                                                                                                              ");\r
294                 \r
295                 shaders_[core::pixel_format::ycbcra] = shader_program(common_vertex, common_fragment +\r
296 \r
297                         "void main()                                                                                                                    "\r
298                         "{                                                                                                                                              "\r
299                         "       float y  = texture2D(plane[0], gl_TexCoord[0].st).r;                            "\r
300                         "       float cb = texture2D(plane[1], gl_TexCoord[0].st).r;                            "\r
301                         "       float cr = texture2D(plane[2], gl_TexCoord[0].st).r;                            "\r
302                         "       float a  = 1.0;                                                                                                         "\r
303                         "       if(local_key)                                                                                                           "\r
304                         "               a = texture2D(plane[3], gl_TexCoord[1].st).r;                                   "\r
305                         "       else                                                                                                                            "\r
306                         "               a  = texture2D(plane[3], gl_TexCoord[0].st).r;                                  "\r
307                         "       if(layer_key)                                                                                                           "\r
308                         "               a *= texture2D(plane[4], gl_TexCoord[1].st).r;                                  "\r
309                         "       if(HD)                                                                                                                          "\r
310                         "               gl_FragColor = ycbcra_to_bgra_hd(y, cb, cr, a) * gl_Color * gain;"\r
311                         "       else                                                                                                                            "\r
312                         "               gl_FragColor = ycbcra_to_bgra_sd(y, cb, cr, a) * gl_Color * gain;"\r
313                         "}                                                                                                                                              ");\r
314                 }\r
315                 return shaders_;\r
316         }\r
317 };\r
318 \r
319 image_kernel::image_kernel() : impl_(new implementation()){}\r
320 \r
321 void image_kernel::draw(size_t width, size_t height, const core::pixel_format_desc& pix_desc, const core::image_transform& transform, bool local_key, bool layer_key)\r
322 {\r
323         if(transform.get_opacity() < 0.001)\r
324                 return;\r
325 \r
326         GL(glEnable(GL_TEXTURE_2D));\r
327         GL(glDisable(GL_DEPTH_TEST));   \r
328 \r
329         impl_->shaders()[pix_desc.pix_fmt].use();\r
330 \r
331         GL(glUniform1f(impl_->shaders()[pix_desc.pix_fmt].get_location("gain"), static_cast<GLfloat>(transform.get_gain())));\r
332         GL(glUniform1i(impl_->shaders()[pix_desc.pix_fmt].get_location("HD"), pix_desc.planes.at(0).height > 700 ? 1 : 0));\r
333         GL(glUniform1i(impl_->shaders()[pix_desc.pix_fmt].get_location("local_key"), local_key ? 1 : 0));\r
334         GL(glUniform1i(impl_->shaders()[pix_desc.pix_fmt].get_location("layer_key"), layer_key ? 1 : 0));\r
335 \r
336         if(transform.get_mode() == core::video_mode::upper)\r
337                 glPolygonStipple(upper_pattern);\r
338         else if(transform.get_mode() == core::video_mode::lower)\r
339                 glPolygonStipple(lower_pattern);\r
340         else\r
341                 glPolygonStipple(progressive_pattern);\r
342                         \r
343         GL(glColor4d(1.0, 1.0, 1.0, transform.get_opacity()));\r
344         GL(glViewport(0, 0, width, height));\r
345                                                 \r
346         auto m_p = transform.get_clip_translation();\r
347         auto m_s = transform.get_clip_scale();\r
348         double w = static_cast<double>(width);\r
349         double h = static_cast<double>(height);\r
350 \r
351         GL(glEnable(GL_SCISSOR_TEST));\r
352         GL(glScissor(static_cast<size_t>(m_p[0]*w), static_cast<size_t>(m_p[1]*h), static_cast<size_t>(m_s[0]*w), static_cast<size_t>(m_s[1]*h)));\r
353                         \r
354         auto f_p = transform.get_fill_translation();\r
355         auto f_s = transform.get_fill_scale();\r
356                         \r
357         glBegin(GL_QUADS);\r
358                 glMultiTexCoord2d(GL_TEXTURE0, 0.0, 0.0); glMultiTexCoord2d(GL_TEXTURE1,  f_p[0]        ,  f_p[1]        );             glVertex2d( f_p[0]        *2.0-1.0,  f_p[1]        *2.0-1.0);\r
359                 glMultiTexCoord2d(GL_TEXTURE0, 1.0, 0.0); glMultiTexCoord2d(GL_TEXTURE1, (f_p[0]+f_s[0]),  f_p[1]        );             glVertex2d((f_p[0]+f_s[0])*2.0-1.0,  f_p[1]        *2.0-1.0);\r
360                 glMultiTexCoord2d(GL_TEXTURE0, 1.0, 1.0); glMultiTexCoord2d(GL_TEXTURE1, (f_p[0]+f_s[0]), (f_p[1]+f_s[1]));             glVertex2d((f_p[0]+f_s[0])*2.0-1.0, (f_p[1]+f_s[1])*2.0-1.0);\r
361                 glMultiTexCoord2d(GL_TEXTURE0, 0.0, 1.0); glMultiTexCoord2d(GL_TEXTURE1,  f_p[0]        , (f_p[1]+f_s[1]));             glVertex2d( f_p[0]        *2.0-1.0, (f_p[1]+f_s[1])*2.0-1.0);\r
362         glEnd();\r
363         GL(glDisable(GL_SCISSOR_TEST)); \r
364 }\r
365 \r
366 }}