fix make_shader segment count, repair mask tweak keyfrm updates for xlat,rotate,scale
[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         fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
202                 ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ),
203                 type, severity, message );
204 }
205 #endif
206
207 bool BC_WindowBase::glx_make_current(GLXDrawable draw)
208 {
209         bool ret = glx_make_current(draw, glx_win_context);
210 #ifdef GL_BUG
211         //Enabling OpenGL debug output
212         glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
213         glEnable(GL_DEBUG_OUTPUT);
214         glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
215         glDebugMessageCallback(glDebugCallback, 0);
216         glEnable(GL_DEBUG_OUTPUT);
217 #endif
218         return ret;
219 }
220
221 #endif
222
223 void BC_WindowBase::enable_opengl()
224 {
225 #ifdef HAVE_GL
226         glx_win = glx_window();
227         if( !glx_win ) {
228                 printf("BC_WindowBase::enable_opengl %d: no glx window\n", __LINE__);
229                 exit(1);
230         }
231         GLXContext glx_context = glx_get_context();
232         if( !glx_context ) {
233                 printf("BC_WindowBase::enable_opengl %d: no glx context\n", __LINE__);
234                 exit(1);
235         }
236         top_level->sync_display();
237         get_synchronous()->is_pbuffer = 0;
238         get_synchronous()->current_window = this;
239         glx_make_current(glx_win, glx_context);
240 #endif
241 }
242
243 void BC_WindowBase::disable_opengl()
244 {
245 #ifdef HAVE_GL
246 //      unsigned long valuemask = CWEventMask;
247 //      XSetWindowAttributes attributes;
248 //      attributes.event_mask = DEFAULT_EVENT_MASKS;
249 //      XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
250 #endif
251 }
252
253 void BC_WindowBase::flip_opengl()
254 {
255 #ifdef HAVE_GL
256         glXSwapBuffers(top_level->display, glx_win);
257         glFlush();
258 #endif
259 }
260
261 int BC_WindowBase::get_shader(unsigned int *handle, const char *vert, const char *frag)
262 {
263         return get_resources()->get_synchronous()->get_shader(handle, vert, frag);
264 }
265
266 void BC_WindowBase::put_shader(unsigned int handle, const char *vert, const char *frag)
267 {
268         get_resources()->get_synchronous()->put_shader(handle, vert, frag);
269 }
270
271 int BC_WindowBase::get_opengl_server_version()
272 {
273 #ifdef HAVE_GL
274         int maj, min;
275         if(glXQueryVersion(get_display(), &maj, &min))
276                 return 100 * maj + min;
277 #endif
278         return 0;
279 }