upgrade to ffmpeg 4.2, rework mask for speedup
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcwindow3d.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #define GL_GLEXT_PROTOTYPES
23 #include "bcpixmap.h"
24 #include "bcresources.h"
25 #include "bcsignals.h"
26 #include "bcsynchronous.h"
27 #include "bcwindowbase.h"
28 #include "language.h"
29
30 // OpenGL functions in BC_WindowBase
31
32 #ifdef HAVE_GL
33 int BC_WindowBase::glx_fb_configs(int *attrs, GLXFBConfig *&cfgs)
34 {
35         int ncfgs = 0;
36         cfgs = glXChooseFBConfig(get_display(), get_screen(), attrs, &ncfgs);
37         if( !cfgs ) ncfgs = 0;
38         else if( !ncfgs && cfgs ) { XFree(cfgs);  cfgs = 0; }
39         return ncfgs;
40 }
41
42 // expects prefix of attrs to be:
43 //      GLX_CONFIG_CAVEAT,      <opt>,
44 //      GLX_DRAWABLE_TYPE,      <opt>,
45 //      GLX_DOUBLEBUFFER,       True,
46 int BC_WindowBase::glx_test_fb_configs(int *attrs, GLXFBConfig *&cfgs,
47                 const char *msg, int &msgs)
48 {
49         int ncfgs = glx_fb_configs(attrs+2, cfgs);
50         if( ncfgs ) return ncfgs;
51         if( msgs < 1 ) { ++msgs; /* printf(_("%s: trying fallback 1\n"), msg); */ }
52         ncfgs = glx_fb_configs(attrs+0, cfgs);
53         if( ncfgs ) return ncfgs;
54         if( msgs < 2 ) { ++msgs; /* printf(_("%s: trying single buffering\n"), msg); */ }
55         attrs[5] = False;
56         ncfgs = glx_fb_configs(attrs+0, cfgs);
57         if( ncfgs ) return ncfgs;
58         if( msgs < 3 ) { ++msgs; /* printf(_("%s: trying fallback 2\n"), msg); */ }
59         ncfgs = glx_fb_configs(attrs+2, cfgs);
60         if( ncfgs ) return ncfgs;
61         if( msgs < 4 ) { ++msgs; /* printf(_("%s: trying attributes None\n"), msg); */ }
62         ncfgs = glx_fb_configs(None, cfgs);
63         if( ncfgs ) return ncfgs;
64         disable_opengl();
65         printf(_("%s: opengl initialization failed failed\n"), msg);
66         return 0;
67 }
68
69 GLXFBConfig *BC_WindowBase::glx_window_fb_configs()
70 {
71         static int msgs = 0;
72         if( !glx_fbcfgs_window ) {
73                 int fb_attrs[] = {
74                         GLX_CONFIG_CAVEAT,      GLX_SLOW_CONFIG,
75                         GLX_DRAWABLE_TYPE,      GLX_WINDOW_BIT | GLX_PBUFFER_BIT | GLX_PIXMAP_BIT,
76                         GLX_DOUBLEBUFFER,       True,
77                         GLX_RENDER_TYPE,        GLX_RGBA_BIT,
78                         GLX_ACCUM_RED_SIZE,     1,
79                         GLX_ACCUM_GREEN_SIZE,   1,
80                         GLX_ACCUM_BLUE_SIZE,    1,
81                         GLX_ACCUM_ALPHA_SIZE,   1,
82                         GLX_RED_SIZE,           8,
83                         GLX_GREEN_SIZE,         8,
84                         GLX_BLUE_SIZE,          8,
85                         GLX_ALPHA_SIZE,         8,
86                         None
87                 };
88                 n_fbcfgs_window = glx_test_fb_configs(fb_attrs, glx_fbcfgs_window,
89                         "BC_WindowBase::glx_window_fb_configs", msgs);
90         }
91         return glx_fbcfgs_window;
92 }
93
94 Visual *BC_WindowBase::get_glx_visual(Display *display)
95 {
96         Visual *visual = 0;
97         XVisualInfo *vis_info = 0;
98         GLXFBConfig *fb_cfgs = glx_window_fb_configs();
99         if( fb_cfgs ) {
100                 for( int i=0; !vis_info && i<n_fbcfgs_window; ++i ) {
101                         if( vis_info ) { XFree(vis_info);  vis_info = 0; }
102                         glx_fb_config = fb_cfgs[i];
103                         vis_info = glXGetVisualFromFBConfig(display, glx_fb_config);
104                 }
105         }
106         if( vis_info ) {
107                 visual = vis_info->visual;
108                 XFree(vis_info);
109         }
110         else
111                 glx_fb_config = 0;
112         return visual;
113 }
114
115 GLXFBConfig *BC_WindowBase::glx_pbuffer_fb_configs()
116 {
117         static int msgs = 0;
118         if( !glx_fbcfgs_pbuffer ) {
119                 int fb_attrs[] = {
120                         GLX_CONFIG_CAVEAT,      GLX_SLOW_CONFIG,
121                         GLX_DRAWABLE_TYPE,      GLX_WINDOW_BIT | GLX_PBUFFER_BIT | GLX_PIXMAP_BIT,
122                         GLX_DOUBLEBUFFER,       True, //False,
123                         GLX_RENDER_TYPE,        GLX_RGBA_BIT,
124                         GLX_ACCUM_RED_SIZE,     1,
125                         GLX_ACCUM_GREEN_SIZE,   1,
126                         GLX_ACCUM_BLUE_SIZE,    1,
127                         GLX_ACCUM_ALPHA_SIZE,   1,
128                         GLX_RED_SIZE,           8,
129                         GLX_GREEN_SIZE,         8,
130                         GLX_BLUE_SIZE,          8,
131                         GLX_ALPHA_SIZE,         8,
132                         None
133                 };
134                 n_fbcfgs_pbuffer = glx_test_fb_configs(fb_attrs, glx_fbcfgs_pbuffer,
135                         "BC_WindowBase::glx_pbuffer_fb_configs", msgs);
136         }
137         return glx_fbcfgs_pbuffer;
138 }
139
140 GLXFBConfig *BC_WindowBase::glx_pixmap_fb_configs()
141 {
142         static int msgs = 0;
143         if( !glx_fbcfgs_pixmap ) {
144                 static int fb_attrs[] = {
145                         GLX_CONFIG_CAVEAT,      GLX_SLOW_CONFIG,
146                         GLX_DRAWABLE_TYPE,      GLX_PIXMAP_BIT | GLX_PBUFFER_BIT,
147                         GLX_DOUBLEBUFFER,       True, //False,
148                         GLX_RENDER_TYPE,        GLX_RGBA_BIT,
149                         GLX_RED_SIZE,           8,
150                         GLX_GREEN_SIZE,         8,
151                         GLX_BLUE_SIZE,          8,
152                         GLX_ALPHA_SIZE,         8,
153                         None
154                 };
155                 n_fbcfgs_pixmap = glx_test_fb_configs(fb_attrs, glx_fbcfgs_pixmap,
156                         "BC_WindowBase::glx_pixmap_fb_configs", msgs);
157         }
158         return glx_fbcfgs_pixmap;
159 }
160
161 GLXContext BC_WindowBase::glx_get_context()
162 {
163         if( !glx_win_context && top_level->glx_fb_config )
164                 glx_win_context = glXCreateNewContext(
165                         top_level->get_display(), top_level->glx_fb_config,
166                         GLX_RGBA_TYPE, 0, True);
167         if( !glx_win_context )
168                 printf("BC_WindowBase::get_glx_context %d: failed\n", __LINE__);
169         return glx_win_context;
170 }
171
172 void BC_WindowBase::sync_lock(const char *cp)
173 {
174         get_synchronous()->sync_lock(cp);
175 }
176
177 void BC_WindowBase::sync_unlock()
178 {
179         get_synchronous()->sync_unlock();
180 }
181
182 GLXWindow BC_WindowBase::glx_window()
183 {
184         if( !glx_win ) {
185                 glx_win = glXCreateWindow(top_level->display, top_level->glx_fb_config, win, 0);
186         }
187         return glx_win;
188 }
189
190 bool BC_WindowBase::glx_make_current(GLXDrawable draw, GLXContext glx_ctxt)
191 {
192         return glXMakeContextCurrent(get_display(), draw, draw, glx_ctxt);
193 }
194
195 //#define GL_BUG
196 #ifdef GL_BUG
197 static void GLAPIENTRY glDebugCallback(GLenum source, GLenum type,
198         GLuint id, GLenum severity, GLsizei length, const GLchar* message,
199         const void* userParam)
200 {
201         if( type == GL_DEBUG_TYPE_OTHER &&
202             severity == GL_DEBUG_SEVERITY_NOTIFICATION ) return;
203         fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
204                 ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ),
205                 type, severity, message );
206 }
207 #endif
208
209 bool BC_WindowBase::glx_make_current(GLXDrawable draw)
210 {
211         bool ret = glx_make_current(draw, glx_win_context);
212 #ifdef GL_BUG
213         //Enabling OpenGL debug output
214         glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
215         glEnable(GL_DEBUG_OUTPUT);
216         glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
217         glDebugMessageCallback(glDebugCallback, 0);
218         glEnable(GL_DEBUG_OUTPUT);
219 #endif
220         return ret;
221 }
222
223 #endif
224
225 void BC_WindowBase::enable_opengl()
226 {
227 #ifdef HAVE_GL
228         glx_win = glx_window();
229         if( !glx_win ) {
230                 printf("BC_WindowBase::enable_opengl %d: no glx window\n", __LINE__);
231                 exit(1);
232         }
233         GLXContext glx_context = glx_get_context();
234         if( !glx_context ) {
235                 printf("BC_WindowBase::enable_opengl %d: no glx context\n", __LINE__);
236                 exit(1);
237         }
238         top_level->sync_display();
239         get_synchronous()->is_pbuffer = 0;
240         get_synchronous()->current_window = this;
241         glx_make_current(glx_win, glx_context);
242 #endif
243 }
244
245 void BC_WindowBase::disable_opengl()
246 {
247 #ifdef HAVE_GL
248 //      unsigned long valuemask = CWEventMask;
249 //      XSetWindowAttributes attributes;
250 //      attributes.event_mask = DEFAULT_EVENT_MASKS;
251 //      XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
252 #endif
253 }
254
255 void BC_WindowBase::flip_opengl()
256 {
257 #ifdef HAVE_GL
258         glXSwapBuffers(top_level->display, glx_win);
259         glFlush();
260 #endif
261 }
262
263 int BC_WindowBase::get_shader(unsigned int *handle, const char *vert, const char *frag)
264 {
265         return get_resources()->get_synchronous()->get_shader(handle, vert, frag);
266 }
267
268 void BC_WindowBase::put_shader(unsigned int handle, const char *vert, const char *frag)
269 {
270         get_resources()->get_synchronous()->put_shader(handle, vert, frag);
271 }
272
273 int BC_WindowBase::get_opengl_server_version()
274 {
275 #ifdef HAVE_GL
276         int maj, min;
277         if(glXQueryVersion(get_display(), &maj, &min))
278                 return 100 * maj + min;
279 #endif
280         return 0;
281 }