57118e7421bba74dedbb056bc039ef5e850155d8
[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 bool BC_WindowBase::glx_make_current(GLXDrawable draw)
196 {
197         return glx_make_current(draw, glx_win_context);
198 }
199
200 #endif
201
202 void BC_WindowBase::enable_opengl()
203 {
204 #ifdef HAVE_GL
205         glx_win = glx_window();
206         if( !glx_win ) {
207                 printf("BC_WindowBase::enable_opengl %d: no glx window\n", __LINE__);
208                 exit(1);
209         }
210         GLXContext glx_context = glx_get_context();
211         if( !glx_context ) {
212                 printf("BC_WindowBase::enable_opengl %d: no glx context\n", __LINE__);
213                 exit(1);
214         }
215         top_level->sync_display();
216         get_synchronous()->is_pbuffer = 0;
217         get_synchronous()->current_window = this;
218         glx_make_current(glx_win, glx_context);
219 #endif
220 }
221
222 void BC_WindowBase::disable_opengl()
223 {
224 #ifdef HAVE_GL
225 //      unsigned long valuemask = CWEventMask;
226 //      XSetWindowAttributes attributes;
227 //      attributes.event_mask = DEFAULT_EVENT_MASKS;
228 //      XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
229 #endif
230 }
231
232 void BC_WindowBase::flip_opengl()
233 {
234 #ifdef HAVE_GL
235         glXSwapBuffers(top_level->display, glx_win);
236         glFlush();
237 #endif
238 }
239
240 unsigned int BC_WindowBase::get_shader(char *source, int *got_it)
241 {
242         return get_resources()->get_synchronous()->get_shader(source, got_it);
243 }
244
245 void BC_WindowBase::put_shader(unsigned int handle, char *source)
246 {
247         get_resources()->get_synchronous()->put_shader(handle, source);
248 }
249
250 int BC_WindowBase::get_opengl_server_version()
251 {
252 #ifdef HAVE_GL
253         int maj, min;
254         if(glXQueryVersion(get_display(), &maj, &min))
255                 return 100 * maj + min;
256 #endif
257         return 0;
258 }