]> icculus.org git repositories - divverent/netradiant.git/blob - libs/gtkutil/glwidget.cpp
if a font was not found, fall back to fixed or courier new - should fix "missing...
[divverent/netradiant.git] / libs / gtkutil / glwidget.cpp
1 /*
2 Copyright (C) 2001-2006, William Joseph.
3 All Rights Reserved.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 // OpenGL widget based on GtkGLExt
23
24 #include "glwidget.h"
25
26 #include "debugging/debugging.h"
27
28 #include "igl.h"
29
30 #include <gtk/gtkdrawingarea.h>
31 #include <gtk/gtkglwidget.h>
32
33 #include "pointer.h"
34
35 void (*GLWidget_sharedContextCreated)() = 0;
36 void (*GLWidget_sharedContextDestroyed)() = 0;
37
38
39 typedef int* attribs_t;
40 struct config_t
41 {
42   const char* name;
43   attribs_t attribs;
44 };
45 typedef const config_t* configs_iterator;
46
47 int config_rgba32[] = {
48   GDK_GL_RGBA,
49   GDK_GL_DOUBLEBUFFER,
50   GDK_GL_BUFFER_SIZE, 24,
51   GDK_GL_ATTRIB_LIST_NONE,
52 };
53
54 int config_rgba[] = {
55   GDK_GL_RGBA,
56   GDK_GL_DOUBLEBUFFER,
57   GDK_GL_BUFFER_SIZE, 16,
58   GDK_GL_ATTRIB_LIST_NONE,
59 };
60
61 const config_t configs[] = {
62   {
63     "colour-buffer = 32bpp, depth-buffer = none",
64     config_rgba32,
65   },
66   {
67     "colour-buffer = 16bpp, depth-buffer = none",
68     config_rgba,
69   }
70 };
71
72 GdkGLConfig* glconfig_new()
73 {
74   GdkGLConfig* glconfig = 0;
75
76   for(configs_iterator i = configs, end = configs + 2; i != end; ++i)
77   {
78     glconfig = gdk_gl_config_new((*i).attribs);
79     if(glconfig != 0)
80     {
81       globalOutputStream() << "OpenGL window configuration: " << (*i).name << "\n";
82       return glconfig;
83     }
84   }
85
86   globalOutputStream() << "OpenGL window configuration: colour-buffer = auto, depth-buffer = none\n";
87   return gdk_gl_config_new_by_mode((GdkGLConfigMode)(GDK_GL_MODE_RGBA | GDK_GL_MODE_DOUBLE));
88 }
89
90 int config_rgba32_depth32[] = {
91   GDK_GL_RGBA,
92   GDK_GL_DOUBLEBUFFER,
93   GDK_GL_BUFFER_SIZE, 24,
94   GDK_GL_DEPTH_SIZE, 32,
95   GDK_GL_ATTRIB_LIST_NONE,
96 };
97
98 int config_rgba32_depth24[] = {
99   GDK_GL_RGBA,
100   GDK_GL_DOUBLEBUFFER,
101   GDK_GL_BUFFER_SIZE, 24,
102   GDK_GL_DEPTH_SIZE, 24,
103   GDK_GL_ATTRIB_LIST_NONE,
104 };
105
106 int config_rgba32_depth16[] = {
107   GDK_GL_RGBA,
108   GDK_GL_DOUBLEBUFFER,
109   GDK_GL_BUFFER_SIZE, 24,
110   GDK_GL_DEPTH_SIZE, 16,
111   GDK_GL_ATTRIB_LIST_NONE,
112 };
113
114 int config_rgba32_depth[] = {
115   GDK_GL_RGBA,
116   GDK_GL_DOUBLEBUFFER,
117   GDK_GL_BUFFER_SIZE, 24,
118   GDK_GL_DEPTH_SIZE, 1,
119   GDK_GL_ATTRIB_LIST_NONE,
120 };
121
122 int config_rgba_depth16[] = {
123   GDK_GL_RGBA,
124   GDK_GL_DOUBLEBUFFER,
125   GDK_GL_BUFFER_SIZE, 16,
126   GDK_GL_DEPTH_SIZE, 16,
127   GDK_GL_ATTRIB_LIST_NONE,
128 };
129
130 int config_rgba_depth[] = {
131   GDK_GL_RGBA,
132   GDK_GL_DOUBLEBUFFER,
133   GDK_GL_BUFFER_SIZE, 16,
134   GDK_GL_DEPTH_SIZE, 1,
135   GDK_GL_ATTRIB_LIST_NONE,
136 };
137
138 const config_t configs_with_depth[] = 
139 {
140   {
141     "colour-buffer = 32bpp, depth-buffer = 32bpp",
142     config_rgba32_depth32,
143   },
144   {
145     "colour-buffer = 32bpp, depth-buffer = 24bpp",
146     config_rgba32_depth24,
147   },
148   {
149     "colour-buffer = 32bpp, depth-buffer = 16bpp",
150     config_rgba32_depth16,
151   },
152   {
153     "colour-buffer = 32bpp, depth-buffer = auto",
154     config_rgba32_depth,
155   },
156   {
157     "colour-buffer = 16bpp, depth-buffer = 16bpp",
158     config_rgba_depth16,
159   },
160   {
161     "colour-buffer = auto, depth-buffer = auto",
162     config_rgba_depth,
163   },
164 };
165
166 GdkGLConfig* glconfig_new_with_depth()
167 {
168   GdkGLConfig* glconfig = 0;
169
170   for(configs_iterator i = configs_with_depth, end = configs_with_depth + 6; i != end; ++i)
171   {
172     glconfig = gdk_gl_config_new((*i).attribs);
173     if(glconfig != 0)
174     {
175       globalOutputStream() << "OpenGL window configuration: " << (*i).name << "\n";
176       return glconfig;
177     }
178   }
179
180   globalOutputStream() << "OpenGL window configuration: colour-buffer = auto, depth-buffer = auto (fallback)\n";
181   return gdk_gl_config_new_by_mode((GdkGLConfigMode)(GDK_GL_MODE_RGBA | GDK_GL_MODE_DOUBLE | GDK_GL_MODE_DEPTH));
182 }
183
184 unsigned int g_context_count = 0;
185
186 namespace
187 {
188   GtkWidget* g_shared = 0;
189 }
190
191 gint glwidget_context_created(GtkWidget* widget, gpointer data)
192 {
193   if(++g_context_count == 1)
194   {
195     g_shared = widget;
196     gtk_widget_ref(g_shared);
197
198     glwidget_make_current(g_shared);
199     GlobalOpenGL().contextValid = true;
200
201     GLWidget_sharedContextCreated();
202   }
203   return FALSE;
204 }
205
206 gint glwidget_context_destroyed(GtkWidget* widget, gpointer data)
207 {
208   if(--g_context_count == 0)
209   {
210     GlobalOpenGL().contextValid = false;
211
212     GLWidget_sharedContextDestroyed();
213
214     gtk_widget_unref(g_shared);
215     g_shared = 0;
216   }
217   return FALSE;
218 }
219
220 gboolean glwidget_enable_gl(GtkWidget* widget, GtkWidget* widget2, gpointer data)
221 {
222   if(widget2 == 0 && !gtk_widget_is_gl_capable(widget))
223   {
224     GdkGLConfig* glconfig = (g_object_get_data(G_OBJECT(widget), "zbuffer")) ? glconfig_new_with_depth() : glconfig_new();
225     ASSERT_MESSAGE(glconfig != 0, "failed to create OpenGL config");
226
227     gtk_widget_set_gl_capability(widget, glconfig, g_shared != 0 ? gtk_widget_get_gl_context(g_shared) : 0,  TRUE, GDK_GL_RGBA_TYPE);
228
229     gtk_widget_realize(widget);
230     if(g_shared == 0)
231     {
232       g_shared = widget;
233     }
234
235     // free glconfig?
236   }
237   return FALSE;
238 }
239
240 GtkWidget* glwidget_new(gboolean zbuffer)
241 {
242   GtkWidget* widget = gtk_drawing_area_new();
243
244   g_object_set_data(G_OBJECT(widget), "zbuffer", gint_to_pointer(zbuffer));
245
246   g_signal_connect(G_OBJECT(widget), "hierarchy-changed", G_CALLBACK(glwidget_enable_gl), 0);
247
248   g_signal_connect(G_OBJECT(widget), "realize", G_CALLBACK(glwidget_context_created), 0);
249   g_signal_connect(G_OBJECT(widget), "unrealize", G_CALLBACK(glwidget_context_destroyed), 0);
250
251   return widget;
252 }
253
254 void glwidget_destroy_context (GtkWidget *widget)
255 {
256 }
257
258 void glwidget_create_context (GtkWidget *widget)
259 {
260 }
261
262 void glwidget_swap_buffers (GtkWidget *widget)
263 {
264   GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
265   gdk_gl_drawable_swap_buffers (gldrawable);
266 }
267
268 gboolean glwidget_make_current (GtkWidget *widget)
269 {
270   GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
271   GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
272   return gdk_gl_drawable_gl_begin (gldrawable, glcontext);
273 }
274