4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
22 #define GL_GLEXT_PROTOTYPES
24 #include "bcresources.h"
25 #include "bcsignals.h"
26 #include "bcsynchronous.h"
27 #include "bcwindowbase.h"
29 // OpenGL functions in BC_WindowBase
32 int BC_WindowBase::glx_fb_configs(int *attrs, GLXFBConfig *&cfgs)
35 cfgs = glXChooseFBConfig(get_display(), get_screen(), attrs, &ncfgs);
36 if( !cfgs ) ncfgs = 0;
37 else if( !ncfgs && cfgs ) { XFree(cfgs); cfgs = 0; }
41 // expects prefix of attrs to be:
42 // GLX_CONFIG_CAVEAT, <opt>,
43 // GLX_DRAWABLE_TYPE, <opt>,
44 // GLX_DOUBLEBUFFER, True,
45 int BC_WindowBase::glx_test_fb_configs(int *attrs, GLXFBConfig *&cfgs,
46 const char *msg, int &msgs)
48 int ncfgs = glx_fb_configs(attrs+2, cfgs);
49 if( ncfgs ) return ncfgs;
50 if( msgs < 1 ) { ++msgs; printf("%s: trying fallback 1\n", msg); }
51 ncfgs = glx_fb_configs(attrs+0, cfgs);
52 if( ncfgs ) return ncfgs;
53 if( msgs < 2 ) { ++msgs; printf("%s: trying single buffering\n", msg); }
55 ncfgs = glx_fb_configs(attrs+0, cfgs);
56 if( ncfgs ) return ncfgs;
57 if( msgs < 3 ) { ++msgs; printf("%s: trying fallback 2\n", msg); }
58 ncfgs = glx_fb_configs(attrs+2, cfgs);
59 if( ncfgs ) return ncfgs;
60 if( msgs < 4 ) { ++msgs; printf("%s: trying attributes None\n", msg); }
61 ncfgs = glx_fb_configs(None, cfgs);
62 if( ncfgs ) return ncfgs;
64 printf("%s: opengl initialization failed failed\n", msg);
68 GLXFBConfig *BC_WindowBase::glx_window_fb_configs()
71 if( !glx_fbcfgs_window ) {
73 GLX_CONFIG_CAVEAT, GLX_SLOW_CONFIG,
74 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PBUFFER | GLX_PIXMAP_BIT,
75 GLX_DOUBLEBUFFER, True,
76 GLX_RENDER_TYPE, GLX_RGBA_BIT,
77 GLX_ACCUM_RED_SIZE, 1,
78 GLX_ACCUM_GREEN_SIZE, 1,
79 GLX_ACCUM_BLUE_SIZE, 1,
80 GLX_ACCUM_ALPHA_SIZE, 1,
87 n_fbcfgs_window = glx_test_fb_configs(fb_attrs, glx_fbcfgs_window,
88 "BC_WindowBase::glx_window_fb_configs", msgs);
90 return glx_fbcfgs_window;
93 Visual *BC_WindowBase::get_glx_visual(Display *display)
96 XVisualInfo *vis_info = 0;
97 GLXFBConfig *fb_cfgs = glx_window_fb_configs();
99 for( int i=0; !vis_info && i<n_fbcfgs_window; ++i ) {
100 if( vis_info ) { XFree(vis_info); vis_info = 0; }
101 glx_fb_config = fb_cfgs[i];
102 vis_info = glXGetVisualFromFBConfig(display, glx_fb_config);
106 visual = vis_info->visual;
114 GLXFBConfig *BC_WindowBase::glx_pbuffer_fb_configs()
117 if( !glx_fbcfgs_pbuffer ) {
119 GLX_CONFIG_CAVEAT, GLX_SLOW_CONFIG,
120 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PBUFFER | GLX_PIXMAP_BIT,
121 GLX_DOUBLEBUFFER, True, //False,
122 GLX_RENDER_TYPE, GLX_RGBA_BIT,
123 GLX_ACCUM_RED_SIZE, 1,
124 GLX_ACCUM_GREEN_SIZE, 1,
125 GLX_ACCUM_BLUE_SIZE, 1,
126 GLX_ACCUM_ALPHA_SIZE, 1,
133 n_fbcfgs_pbuffer = glx_test_fb_configs(fb_attrs, glx_fbcfgs_pbuffer,
134 "BC_WindowBase::glx_pbuffer_fb_configs", msgs);
136 return glx_fbcfgs_pbuffer;
139 GLXFBConfig *BC_WindowBase::glx_pixmap_fb_configs()
142 if( !glx_fbcfgs_pixmap ) {
143 static int fb_attrs[] = {
144 GLX_CONFIG_CAVEAT, GLX_SLOW_CONFIG,
145 GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_PBUFFER,
146 GLX_DOUBLEBUFFER, True, //False,
147 GLX_RENDER_TYPE, GLX_RGBA_BIT,
154 n_fbcfgs_pixmap = glx_test_fb_configs(fb_attrs, glx_fbcfgs_pixmap,
155 "BC_WindowBase::glx_pixmap_fb_configs", msgs);
157 return glx_fbcfgs_pixmap;
160 GLXContext BC_WindowBase::glx_get_context()
162 if( !glx_win_context && top_level->glx_fb_config )
163 glx_win_context = glXCreateNewContext(
164 top_level->get_display(), top_level->glx_fb_config,
165 GLX_RGBA_TYPE, 0, True);
166 if( !glx_win_context )
167 printf("BC_WindowBase::get_glx_context %d: failed\n", __LINE__);
168 return glx_win_context;
171 void BC_WindowBase::sync_lock(const char *cp)
173 get_synchronous()->sync_lock(cp);
176 void BC_WindowBase::sync_unlock()
178 get_synchronous()->sync_unlock();
181 GLXWindow BC_WindowBase::glx_window()
184 top_level->options |= GLX_DISPLAY;
185 glx_win = glXCreateWindow(top_level->display, top_level->glx_fb_config, win, 0);
190 bool BC_WindowBase::glx_make_current(GLXDrawable draw, GLXContext glx_ctxt)
192 return glXMakeContextCurrent(get_display(), draw, draw, glx_ctxt);
195 bool BC_WindowBase::glx_make_current(GLXDrawable draw)
197 return glx_make_current(draw, glx_win_context);
202 void BC_WindowBase::enable_opengl()
205 glx_win = glx_window();
207 printf("BC_WindowBase::enable_opengl %d: no glx window\n", __LINE__);
210 GLXContext glx_context = glx_get_context();
212 printf("BC_WindowBase::enable_opengl %d: no glx context\n", __LINE__);
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);
222 void BC_WindowBase::disable_opengl()
225 // unsigned long valuemask = CWEventMask;
226 // XSetWindowAttributes attributes;
227 // attributes.event_mask = DEFAULT_EVENT_MASKS;
228 // XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
232 void BC_WindowBase::flip_opengl()
235 glXSwapBuffers(top_level->display, glx_win);
240 unsigned int BC_WindowBase::get_shader(char *source, int *got_it)
242 return get_resources()->get_synchronous()->get_shader(source, got_it);
245 void BC_WindowBase::put_shader(unsigned int handle, char *source)
247 get_resources()->get_synchronous()->put_shader(handle, source);
250 int BC_WindowBase::get_opengl_server_version()
254 if(glXQueryVersion(get_display(), &maj, &min))
255 return 100 * maj + min;