2 * Copyright (C) 2009-2011 Andy Spencer <andy753421@gmail.com>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 /***************************
21 * GtkGlExt implementation *
22 ***************************/
23 #if defined(SYS_GTKGLEXT)
24 #include <gtk/gtkgl.h>
25 void gtk_gl_enable(GtkWidget *widget)
27 GdkGLConfig *glconfig = gdk_gl_config_new_by_mode(
28 GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH |
29 GDK_GL_MODE_ALPHA | GDK_GL_MODE_DOUBLE);
30 gtk_widget_set_gl_capability(widget,
31 glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
34 void gtk_gl_begin(GtkWidget *widget)
36 GdkGLContext *glcontext = gtk_widget_get_gl_context(widget);
37 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
38 gdk_gl_drawable_gl_begin(gldrawable, glcontext);
41 void gtk_gl_end(GtkWidget *widget)
43 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
44 gdk_gl_drawable_swap_buffers(gldrawable);
45 gdk_gl_drawable_gl_end(gldrawable);
48 void gtk_gl_disable(GtkWidget *widget)
53 /**********************
54 * X11 implementation *
55 **********************/
56 #elif defined(SYS_X11)
59 static gboolean gtk_gl_errors;
60 static int gtk_gl_handler(Display *xdisplay, XErrorEvent *xerror)
65 static GLXContext gtk_gl_create_context(Display *xdisplay, XVisualInfo *xvinfo,
66 GLXContext shared, Bool direct)
68 gtk_gl_errors = FALSE;
69 XSync(xdisplay, False);
70 void *handler = XSetErrorHandler(gtk_gl_handler);
71 GLXContext context = glXCreateContext(xdisplay, xvinfo, shared, direct);
72 XSync(xdisplay, False);
73 XSetErrorHandler(handler);
79 void gtk_gl_enable(GtkWidget *widget)
81 g_debug("GtkGl: enable");
82 GdkScreen *screen = gdk_screen_get_default();
83 Display *xdisplay = GDK_SCREEN_XDISPLAY(screen);
84 gint nscreen = GDK_SCREEN_XNUMBER(screen);
87 int attribs[] = {GLX_RGBA,
96 XVisualInfo *xvinfo = glXChooseVisual(xdisplay, nscreen, attribs);
98 g_error("GtkGl: enable - unable to get valid OpenGL Visual");
99 GLXContext context = 0;
101 context = gtk_gl_create_context(xdisplay, xvinfo, NULL, True);
103 context = gtk_gl_create_context(xdisplay, xvinfo, NULL, False);
105 g_error("Unable to create OpenGL context,"
106 "possible graphics driver problem?");
107 g_debug("GtkGl: direct rendering = %d\n", glXIsDirect(xdisplay, context));
109 g_object_set_data(G_OBJECT(widget), "glcontext", context);
111 /* Fix up visual/colormap */
112 #if GTK_CHECK_VERSION(3,0,0)
113 GdkVisual *visual = gdk_x11_screen_lookup_visual(screen, xvinfo->visualid);
114 gtk_widget_set_visual(widget, visual);
116 GdkVisual *visual = gdk_x11_screen_lookup_visual(screen, xvinfo->visualid);
117 GdkColormap *cmap = gdk_colormap_new(visual, FALSE);
118 gtk_widget_set_colormap(widget, cmap);
119 g_object_unref(cmap);
123 /* Disable GTK double buffering */
124 gtk_widget_set_double_buffered(widget, FALSE);
127 void gtk_gl_begin(GtkWidget *widget)
129 g_debug("GtkGl: begin");
130 Display *xdisplay = GDK_SCREEN_XDISPLAY(gtk_widget_get_screen(widget));
131 Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
132 GLXContext context = g_object_get_data(G_OBJECT(widget), "glcontext");
133 glXMakeCurrent(xdisplay, xwindow, context);
136 void gtk_gl_end(GtkWidget *widget)
138 g_debug("GtkGl: end");
139 Display *xdisplay = GDK_SCREEN_XDISPLAY(gtk_widget_get_screen(widget));
140 Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
141 glXSwapBuffers(xdisplay, xwindow);
144 void gtk_gl_disable(GtkWidget *widget)
146 g_debug("GtkGl: disable");
147 Display *xdisplay = GDK_SCREEN_XDISPLAY(gtk_widget_get_screen(widget));
148 GLXContext context = g_object_get_data(G_OBJECT(widget), "glcontext");
149 glXDestroyContext(xdisplay, context);
153 /************************
154 * Win32 implementation *
155 ************************/
156 #elif defined(SYS_WIN)
158 #include <gdk/gdkwin32.h>
161 /* Windows doens't define OpenGL extensions */
162 static void APIENTRY (*glMultiTexCoord2dvPtr)(int target, const double *v);
163 static void APIENTRY (*glActiveTexturePtr)(int texture);
165 void APIENTRY glMultiTexCoord2dv(int target, const double *v)
167 glMultiTexCoord2dvPtr(target, v);
170 void APIENTRY glActiveTexture(int texture)
172 glActiveTexturePtr(texture);
175 static void init_extensions(void)
177 static gboolean init_done = FALSE;
182 g_debug("GtkGl: init_extensions");
183 const guchar *exts = NULL;
184 if (!(exts = glGetString(GL_EXTENSIONS)))
185 g_error("GtkGl: Unable to query extensions");
186 if (!(glMultiTexCoord2dvPtr = (void*)wglGetProcAddress("glMultiTexCoord2dvARB")))
187 g_error("GtkGl: Unable to load glMultiTexCoord2dv extension:\n%s", exts);
188 if (!(glActiveTexturePtr = (void*)wglGetProcAddress("glActiveTextureARB")))
189 g_error("GtkGl: Unable to load glActiveTexture extension\n%s", exts);
190 g_debug("GtkGl: extensions - glMultiTexCoord2dvPtr=%p glActiveTexturePtr=%p",
191 glMultiTexCoord2dvPtr, glActiveTexturePtr);
194 /* gtkgl implementation */
195 static void on_realize(GtkWidget *widget, gpointer _)
197 g_debug("GtkGl: on_realize");
198 gdk_window_ensure_native(gtk_widget_get_window(widget));
199 gtk_widget_set_double_buffered(widget, FALSE);
201 HWND hwnd = GDK_WINDOW_HWND(gtk_widget_get_window(widget));
202 HDC hDC = GetDC(hwnd);
204 PIXELFORMATDESCRIPTOR pfd = {
205 .nSize = sizeof(pfd),
207 .dwFlags = PFD_DRAW_TO_WINDOW
210 //.dwFlags = PFD_SUPPORT_OPENGL
211 // | PFD_DRAW_TO_WINDOW,
212 .iPixelType = PFD_TYPE_RGBA,
216 .iLayerType = PFD_MAIN_PLANE,
218 int pf = ChoosePixelFormat(hDC, &pfd);
220 g_error("GtkGl: ChoosePixelFormat failed");
221 if (!SetPixelFormat(hDC, pf, &pfd))
222 g_error("GtkGl: SetPixelFormat failed");
223 HGLRC hRC = wglCreateContext(hDC);
225 g_error("GtkGl: wglCreateContext failed");
226 g_object_set_data(G_OBJECT(widget), "glcontext", hRC);
229 void gtk_gl_enable(GtkWidget *widget)
231 g_debug("GtkGl: enable");
232 g_signal_connect(widget, "realize", G_CALLBACK(on_realize), NULL);
235 void gtk_gl_begin(GtkWidget *widget)
237 g_debug("GtkGl: begin");
238 HWND hwnd = GDK_WINDOW_HWND(gtk_widget_get_window(widget));
239 HDC hDC = GetDC(hwnd);
240 HGLRC hRC = g_object_get_data(G_OBJECT(widget), "glcontext");
241 if (!wglMakeCurrent(hDC, hRC))
242 g_error("GtkGl: wglMakeCurrent failed");
246 void gtk_gl_end(GtkWidget *widget)
248 g_debug("GtkGl: end");
249 HWND hwnd = GDK_WINDOW_HWND(gtk_widget_get_window(widget));
250 HDC hDC = GetDC(hwnd);
251 if (!SwapBuffers(hDC))
252 g_error("GtkGl: SwapBuffers failed");
255 void gtk_gl_disable(GtkWidget *widget)
257 g_debug("GtkGl: disable");
258 HGLRC hRC = g_object_get_data(G_OBJECT(widget), "glcontext");
259 wglDeleteContext(hRC);
263 /**************************
264 * Mac OSX implementation *
265 **************************/
266 #elif defined(SYS_MAC)
267 #include <gdk/gdkquartz.h>
268 void gtk_gl_enable(GtkWidget *widget)
270 g_debug("GtkGl: enable");
273 NSOpenGLPixelFormatAttribute attribs[] = {
274 NSOpenGLPFAColorSize, 24,
275 NSOpenGLPFAAlphaSize, 8,
276 NSOpenGLPFADepthSize, 1,
277 NSOpenGLPFADoubleBuffer,
280 NSOpenGLPixelFormat *pix = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
281 NSOpenGLContext *ctx = [[NSOpenGLContext alloc] initWithFormat:pix shareContext:nil];
283 /* Attach to widget */
284 gtk_widget_set_double_buffered(widget, FALSE);
287 g_object_set_data(G_OBJECT(widget), "glcontext", ctx);
290 void gtk_gl_begin(GtkWidget *widget)
292 g_debug("GtkGl: begin");
294 gdk_window_ensure_native(gtk_widget_get_window(widget));
295 gtk_widget_get_allocation(widget, &alloc);
296 gtk_widget_translate_coordinates(widget, gtk_widget_get_toplevel(widget),
297 0, 0, &alloc.x, &alloc.y);
299 NSOpenGLContext *ctx = g_object_get_data(G_OBJECT(widget), "glcontext");
300 GdkWindow *win = gtk_widget_get_window(widget);
301 NSView *view = gdk_quartz_window_get_nsview(win);
302 NSRect rect = NSMakeRect(alloc.x, alloc.y, alloc.width, alloc.height);
305 [ctx makeCurrentContext];
307 [view setFrame:rect];
308 [view setWantsBestResolutionOpenGLSurface:YES];
311 void gtk_gl_end(GtkWidget *widget)
313 g_debug("GtkGl: end");
314 NSOpenGLContext *ctx = g_object_get_data(G_OBJECT(widget), "glcontext");
318 void gtk_gl_disable(GtkWidget *widget)
320 g_debug("GtkGl: disable");
324 /****************************
325 * Undefined implementation *
326 ****************************/
328 #warning "Unimplemented GtkGl"
329 void gtk_gl_enable(GtkWidget *widget) { }
330 void gtk_gl_begin(GtkWidget *widget) { }
331 void gtk_gl_end(GtkWidget *widget) { }
332 void gtk_gl_disable(GtkWidget *widget) { }