FreeBASIC  0.91.0
gfx_driver_opengl_x11.c
Go to the documentation of this file.
1 /* OpenGL gfx driver */
2 
3 #include "../fb_gfx.h"
4 #include "fb_gfx_x11.h"
5 #include "../fb_gfx_gl.h"
6 
7 #if !defined DISABLE_X11 && !defined DISABLE_OPENGL
8 
9 #include <GL/glx.h>
10 
11 /* For compatibility with old Mesa headers */
12 #ifndef GLX_SAMPLE_BUFFERS_ARB
13 # define GLX_SAMPLE_BUFFERS_ARB 100000
14 #endif
15 #ifndef GLX_SAMPLES_ARB
16 # define GLX_SAMPLES_ARB 100001
17 #endif
18 
19 static int driver_init(char *title, int w, int h, int depth, int refresh_rate, int flags);
20 static void driver_exit(void);
21 static void driver_flip(void);
22 
24 {
25  "OpenGL", /* char *name; */
26  driver_init, /* int (*init)(int w, int h, char *title, int fullscreen); */
27  driver_exit, /* void (*exit)(void); */
28  fb_hX11Lock, /* void (*lock)(void); */
29  fb_hX11Unlock, /* void (*unlock)(void); */
30  fb_hX11SetPalette, /* void (*set_palette)(int index, int r, int g, int b); */
31  fb_hX11WaitVSync, /* void (*wait_vsync)(void); */
32  fb_hX11GetMouse, /* int (*get_mouse)(int *x, int *y, int *z, int *buttons, int *clip); */
33  fb_hX11SetMouse, /* void (*set_mouse)(int x, int y, int cursor, int clip); */
34  fb_hX11SetWindowTitle, /* void (*set_window_title)(char *title); */
35  fb_hX11SetWindowPos, /* int (*set_window_pos)(int x, int y); */
36  fb_hX11FetchModes, /* int *(*fetch_modes)(void); */
37  driver_flip, /* void (*flip)(void); */
38  NULL /* void (*poll_events)(void); */
39 };
40 
41 
42 typedef XVisualInfo *(*GLXCHOOSEVISUAL)(Display *, int, int *);
43 typedef GLXContext (*GLXCREATECONTEXT)(Display *, XVisualInfo *, GLXContext, int);
44 typedef void (*GLXDESTROYCONTEXT)(Display *, GLXContext);
45 typedef int (*GLXMAKECURRENT)(Display *, GLXDrawable, GLXContext);
46 typedef void (*GLXSWAPBUFFERS)(Display *, GLXDrawable);
47 
48 typedef struct {
54 } GLXFUNCS;
55 
56 static FB_DYLIB gl_lib = NULL;
57 static GLXFUNCS __fb_glX = { NULL };
58 static GLXContext context;
59 
60 void *fb_hGL_GetProcAddress(const char *proc)
61 {
62  void *addr;
63 
64  if (fb_hDynLoadAlso(gl_lib, &proc, &addr, 1))
65  return NULL;
66 
67  return addr;
68 }
69 
70 static int opengl_window_init(void)
71 {
72  int x = 0, y = 0;
73  int h;
74  char *display_name;
75 
76  if (!(fb_x11.flags & DRIVER_FULLSCREEN)) {
77  x = (XDisplayWidth(fb_x11.display, fb_x11.screen) - fb_x11.w) >> 1;
78  y = (XDisplayHeight(fb_x11.display, fb_x11.screen) - fb_x11.h) >> 1;
79  }
80  fb_hX11InitWindow(x, y);
81 
84  display_name = XDisplayName(NULL);
85  if ((!display_name[0]) || (display_name[0] == ':') || (!strncmp(display_name, "unix:", 5))) {
86  if (fb_hX11EnterFullscreen(&h) || (h != fb_x11.h)) {
88  return -1;
89  }
90  XReparentWindow(fb_x11.display, fb_x11.window, fb_x11.fswindow, 0, 0);
91  XMoveResizeWindow(fb_x11.display, fb_x11.fswindow, 0,0,fb_x11.w, fb_x11.h);
92  XMoveResizeWindow(fb_x11.display, fb_x11.window, 0,0,fb_x11.w, fb_x11.h);
93  }
94  else
95  return -1;
96  }
97 
98  XSync(fb_x11.display, False);
99 
100  return 0;
101 }
102 
103 static void opengl_window_exit(void)
104 {
107 
108  XUnmapWindow(fb_x11.display, fb_x11.window);
111  XUnmapWindow(fb_x11.display, fb_x11.fswindow);
112  XSync(fb_x11.display, False);
113  } else {
114  XUnmapWindow(fb_x11.display, fb_x11.wmwindow);
116  }
117  //usleep(500);
118  XSync(fb_x11.display, False);
119 }
120 
121 static void opengl_window_update(void)
122 {
123 }
124 
125 static int driver_init(char *title, int w, int h, int depth, int refresh_rate, int flags)
126 {
127  const char *glx_funcs[] = {
128  "glXChooseVisual", "glXCreateContext", "glXDestroyContext",
129  "glXMakeCurrent", "glXSwapBuffers", NULL
130  };
131  GLXFUNCS *funcs = &__fb_glX;
132  void **funcs_ptr = (void **)funcs;
133  XVisualInfo *info;
134  int attribs[64] = { GLX_RGBA, GLX_DOUBLEBUFFER, 0 }, *attrib = &attribs[2], *samples_attrib = NULL;
135  int result;
136 
137  fb_hMemSet(&fb_x11, 0, sizeof(fb_x11));
138 
139  context = NULL;
140  info = NULL;
141 
142  if (!(flags & DRIVER_OPENGL))
143  return -1;
145  *attrib++ = GLX_RED_SIZE;
146  *attrib++ = __fb_gl_params.color_red_bits;
147  *attrib++ = GLX_GREEN_SIZE;
148  *attrib++ = __fb_gl_params.color_green_bits;
149  *attrib++ = GLX_BLUE_SIZE;
150  *attrib++ = __fb_gl_params.color_blue_bits;
151  *attrib++ = GLX_ALPHA_SIZE;
152  *attrib++ = __fb_gl_params.color_alpha_bits;
153  *attrib++ = GLX_DEPTH_SIZE;
154  *attrib++ = __fb_gl_params.depth_bits;
155  if (__fb_gl_params.stencil_bits > 0) {
156  *attrib++ = GLX_STENCIL_SIZE;
157  *attrib++ = __fb_gl_params.stencil_bits;
158  }
159  if (__fb_gl_params.accum_bits > 0) {
160  *attrib++ = GLX_ACCUM_RED_SIZE;
161  *attrib++ = __fb_gl_params.accum_red_bits;
162  *attrib++ = GLX_ACCUM_GREEN_SIZE;
163  *attrib++ = __fb_gl_params.accum_green_bits;
164  *attrib++ = GLX_ACCUM_BLUE_SIZE;
165  *attrib++ = __fb_gl_params.accum_blue_bits;
166  *attrib++ = GLX_ACCUM_ALPHA_SIZE;
167  *attrib++ = __fb_gl_params.accum_alpha_bits;
168  }
169  if (__fb_gl_params.num_samples > 0) {
170  *attrib++ = GLX_SAMPLE_BUFFERS_ARB;
171  *attrib++ = GL_TRUE;
172  *attrib++ = GLX_SAMPLES_ARB;
173  samples_attrib = attrib;
174  *attrib++ = 4;
175  }
176  *attrib = None;
177 
181  fb_hXlibInit();
182  fb_x11.display = XOpenDisplay(NULL);
183  if (!fb_x11.display)
184  return -1;
185  fb_x11.screen = XDefaultScreen(fb_x11.display);
186  if (!gl_lib) gl_lib = fb_hDynLoad("libGL.so.1", glx_funcs, funcs_ptr);
187 
188  if (!gl_lib)
189  return -1;
190 
191  do {
192  if ((info = __fb_glX.ChooseVisual(fb_x11.display, fb_x11.screen, attribs))) {
193  fb_x11.visual = info->visual;
194  context = __fb_glX.CreateContext(fb_x11.display, info, NULL, True);
195  if (context)
196  break;
197  XFree(info);
198  info = NULL;
199  }
200  } while ((samples_attrib) && ((*samples_attrib -= 2) >= 0));
201 
202  if (!info) {
203  return -1;
204  }
205 
206  result = fb_hX11Init(title, w, h, info->depth, refresh_rate, flags);
207 
208  XFree(info);
209  info = NULL;
210 
211  if (result)
212  return result;
213 
215 
216  if (fb_hGL_Init(gl_lib, NULL))
217  return -1;
218 
219  if ((samples_attrib) && (*samples_attrib > 0))
221 
222  return 0;
223 }
224 
225 static void driver_exit(void)
226 {
227  if (context) {
228  __fb_glX.MakeCurrent(fb_x11.display, None, NULL);
230  context = NULL;
231  }
232  fb_hX11Exit();
234 }
235 
236 static void driver_flip(void)
237 {
238  fb_hX11Lock();
240  fb_hX11Unlock();
241 }
242 
243 #endif