]> Pileus Git - grits/blob - examples/gl/gl.c
Add GL bindings example program
[grits] / examples / gl / gl.c
1 #include <math.h>
2 #include <gtk/gtk.h>
3 #include <gdk/gdkkeysyms.h>
4
5 //#define USE_CAIRO
6 #define USE_GTKGLEXT
7 //#define USE_GLX
8 //#define USE_WGL
9 //#define USE_CGL
10
11 /************************
12  * Cairo implementation *
13  ************************/
14 #if defined(USE_CAIRO)
15 #include <gdk/gdkwin32.h>
16 gpointer expose_setup(GtkWidget *widget) { return NULL; }
17 gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
18 {
19         GtkAllocation alloc;
20         gtk_widget_get_allocation(widget, &alloc);
21         cairo_t *cairo = gdk_cairo_create(gtk_widget_get_window(widget));
22         cairo_set_source_rgb(cairo, 1, 1, 1);
23         cairo_arc(cairo,
24                 alloc.x + alloc.width/2,
25                 alloc.y + alloc.height/2,
26                 MIN(alloc.width/2,alloc.height/2),
27                 0, 2*G_PI);
28         cairo_fill(cairo);
29         return FALSE;
30 }
31
32
33 /***************************
34  * GtkGlExt implementation *
35  ***************************/
36 #elif defined(USE_GTKGLEXT)
37 #include <gtk/gtkgl.h>
38 #include <GL/gl.h>
39 #include <gdk/gdkwin32.h>
40 void realize(GtkWidget *widget, gpointer user_data)
41 {
42         gdk_window_ensure_native(gtk_widget_get_window(widget));
43 }
44 gpointer expose_setup(GtkWidget *widget)
45 {
46         //GdkGLConfig *glconfig = gdk_gl_config_new_by_mode(
47         //              GDK_GL_MODE_RGBA   | GDK_GL_MODE_DEPTH |
48         //              GDK_GL_MODE_ALPHA);
49         GdkGLConfig *glconfig = gdk_gl_config_new_by_mode(
50                         GDK_GL_MODE_RGBA   | GDK_GL_MODE_DEPTH |
51                         GDK_GL_MODE_ALPHA  | GDK_GL_MODE_DOUBLE);
52         gtk_widget_set_gl_capability(widget,
53                         glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
54         return NULL;
55 }
56 gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
57 {
58         GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
59         g_message("window: w=%x tl=%x",
60                 (guint)GDK_WINDOW_HWND(gtk_widget_get_window(widget)),
61                 (guint)GDK_WINDOW_HWND(gtk_widget_get_window(toplevel)));
62
63         GtkAllocation alloc;
64         gtk_widget_get_allocation(widget, &alloc);
65         GdkGLContext  *glcontext  = gtk_widget_get_gl_context(widget);
66         GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
67         gdk_gl_drawable_gl_begin(gldrawable, glcontext);
68         glViewport(0, 0, alloc.width, alloc.height);
69         glClear(GL_COLOR_BUFFER_BIT);
70         glColor3f(1.0, 1.0, 1.0);
71         glBegin(GL_TRIANGLE_FAN);
72         glVertex2f(0.0, 0.0);
73         for (double i = 0; i < 2*G_PI; i+=(2*G_PI)/100)
74                 glVertex2d(sin(i), cos(i));
75         glEnd();
76         gdk_gl_drawable_swap_buffers(gldrawable);
77         gdk_gl_drawable_gl_end(gldrawable);
78         return FALSE;
79 }
80
81
82 /**********************
83  * X11 implementation *
84  **********************/
85 #elif defined(USE_GLX)
86 #include <GL/gl.h>
87 #include <GL/glx.h>
88 #include <gdk/gdkx.h>
89 void realize(GtkWidget *widget, gpointer user_data)
90 {
91       gdk_window_ensure_native(gtk_widget_get_window(widget));
92 }
93 gpointer expose_setup(GtkWidget *widget)
94 {
95         GdkScreen *screen    = gdk_screen_get_default();
96         Display   *xdisplay  = GDK_SCREEN_XDISPLAY(screen);
97         gint       nscreen   = GDK_SCREEN_XNUMBER(screen);
98
99         /* Create context */
100         int attribs[]        = {GLX_RGBA,
101                                 GLX_RED_SIZE,    1,
102                                 GLX_GREEN_SIZE,  1,
103                                 GLX_BLUE_SIZE,   1,
104                                 GLX_ALPHA_SIZE,  1,
105                                 GLX_DOUBLEBUFFER,
106                                 GLX_DEPTH_SIZE,  1,
107                                 None};
108         XVisualInfo *xvinfo  = glXChooseVisual(xdisplay, nscreen, attribs);
109         GLXContext   context = glXCreateContext(xdisplay, xvinfo, 0, False);
110
111         /* Fix up colormap */
112         GdkVisual   *visual  = gdk_x11_screen_lookup_visual(screen, xvinfo->visualid);
113         GdkColormap *cmap    = gdk_colormap_new(visual, FALSE);
114         gtk_widget_set_colormap(widget, cmap);
115
116         /* Disable GTK double buffering */
117         gtk_widget_set_double_buffered(widget, FALSE);
118
119         return context;
120 }
121 gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, GLXContext context)
122 {
123         /* Make current */
124         Display     *xdisplay = GDK_SCREEN_XDISPLAY(gdk_screen_get_default());
125         Window       xwindow  = GDK_WINDOW_XID(gtk_widget_get_window(widget));
126         glXMakeCurrent(xdisplay, xwindow, context);
127
128         GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
129         g_message("window: w=%x tl=%x",
130                 (guint)GDK_WINDOW_XID(gtk_widget_get_window(widget)),
131                 (guint)GDK_WINDOW_XID(gtk_widget_get_window(toplevel)));
132
133         /* Drawing */
134         GtkAllocation alloc;
135         gtk_widget_get_allocation(widget, &alloc);
136         glViewport(0, 0, alloc.width, alloc.height);
137         glClear(GL_COLOR_BUFFER_BIT);
138         glColor3f(1.0, 1.0, 1.0);
139         glBegin(GL_TRIANGLE_FAN);
140         glVertex2f(0.0, 0.0);
141         for (double i = 0; i < 2*G_PI; i+=(2*G_PI)/100)
142                 glVertex2d(sin(i), cos(i));
143         glEnd();
144
145         /* Swap buffers */
146         glXSwapBuffers(xdisplay, xwindow);
147         return FALSE;
148 }
149
150
151 /************************
152  * Win32 implementation *
153  ************************/
154 #elif defined(USE_WGL)
155 #include <GL/gl.h>
156 #include <windows.h>
157 #include <gdk/gdkwin32.h>
158 void realize(GtkWidget *widget, gpointer user_data)
159 {
160         gdk_window_ensure_native(gtk_widget_get_window(widget));
161 }
162 gpointer expose_setup(GtkWidget *widget)
163 {
164         /* Create context */
165         //HWND  hwnd = GDK_WINDOW_HWND(gtk_widget_get_window(widget));
166         //HGLRC hDC  = GetDC(hwnd);           // get the device context for window
167         //HDC   hRC  = wglCreateContext(hDC); // create rendering context
168         //wglMakeCurrent(hDC,hRC);            // make rendering context current
169
170         /* Delete context */
171         //wglMakeCurrent(hDC,NULL);    // deselect rendering context
172         //wglDeleteContext(hRC);       // delete rendering context
173         //PostQuitMessage(0);          // send wm_quit
174
175         /* Disable GTK double buffering */
176         gtk_widget_set_double_buffered(widget, FALSE);
177         return FALSE;
178 }
179 gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
180 {
181         GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
182         GdkWindow *window   = gtk_widget_get_window(widget);
183         GdkWindow *topwin   = gtk_widget_get_window(toplevel);
184         gdk_window_ensure_native(window);
185
186         PIXELFORMATDESCRIPTOR pfo = {}, pfd = {
187                 .nSize       = sizeof(pfd),
188                 .nVersion    = 1,
189                 .dwFlags     = PFD_DRAW_TO_WINDOW // "Correct" way
190                              | PFD_SUPPORT_OPENGL
191                              | PFD_DOUBLEBUFFER,
192                 //.dwFlags     = PFD_SUPPORT_OPENGL  // Works in wine
193                 //             | PFD_DRAW_TO_WINDOW,
194                 .iPixelType  = PFD_TYPE_RGBA,
195                 .cColorBits  = 24,
196                 .cAlphaBits  = 8,
197                 .cDepthBits  = 32,
198                 .iLayerType  = PFD_MAIN_PLANE,
199         };
200         HWND  hwnd = GDK_WINDOW_HWND(window);
201         HDC   hDC  = GetDC(hwnd);           // get the device context for window
202         int   pf   = ChoosePixelFormat(hDC, &pfd);
203         int   st0  = DescribePixelFormat(hDC, pf, sizeof(pfd), &pfo);
204         int   st1  = SetPixelFormat(hDC, pf, &pfd);
205         HGLRC hRC  = wglCreateContext(hDC);
206         int   st2  = wglMakeCurrent(hDC, hRC);
207
208         g_message("dc: %p, %p, %p", hDC, GetDC(hwnd), wglGetCurrentDC());
209
210         g_message("window: pf=%d st=%d,%d,%d dc=%p rc=%p wins=%x=%x!=%x",
211                 pf, st0,st1,st2, hDC, hRC, (guint)hwnd,
212                 (guint)GDK_WINDOW_HWND(window),
213                 (guint)GDK_WINDOW_HWND(topwin));
214
215         g_message("pdfOut: dwFlags=%lx=%lx, ipt=%x=%x, layer=%x=%x, {c,a,d}bits=%d,%d,%d",
216                 pfo.dwFlags,    pfd.dwFlags,
217                 pfo.iPixelType, pfd.iPixelType,
218                 pfo.iLayerType, pfd.iLayerType,
219                 pfo.cColorBits, pfo.cAlphaBits, pfo.cDepthBits);
220
221         /* Drawing */
222         GtkAllocation alloc = widget->allocation;
223         glViewport(0, 0, alloc.width, alloc.height);
224         g_message("alloc: %dx%d", alloc.width, alloc.height);
225         glClear(GL_COLOR_BUFFER_BIT);
226         glColor3f(1.0, 1.0, 1.0);
227         glBegin(GL_TRIANGLE_FAN);
228         glVertex2f(0.0, 0.0);
229         for (double i = 0; i < 2*G_PI; i+=(2*G_PI)/100)
230                 glVertex2d(sin(i), cos(i));
231         glEnd();
232
233         /* Swap buffers */
234         SwapBuffers(hDC);
235
236         /* Cleanup */
237         wglMakeCurrent(NULL, NULL);
238         wglDeleteContext(hRC);
239         return TRUE;
240 }
241
242
243 /**************************
244  * Mac OSX implementation *
245  **************************/
246 #elif defined(USE_CGL)
247 #include <GL/gl.h>
248 gpointer expose_setup(GtkWidget *widget)
249 {
250         return FALSE;
251 }
252 gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
253 {
254         /* Drawing */
255         GtkAllocation alloc;
256         gtk_widget_get_allocation(widget, &alloc);
257         glViewport(0, 0, alloc.width, alloc.height);
258         glClear(GL_COLOR_BUFFER_BIT);
259         glColor3f(1.0, 1.0, 1.0);
260         glBegin(GL_TRIANGLE_FAN);
261         glVertex2f(0.0, 0.0);
262         for (double i = 0; i < 2*G_PI; i+=(2*G_PI)/100)
263                 glVertex2d(sin(i), cos(i));
264         glEnd();
265         return FALSE;
266 }
267
268
269 /****************************
270  * Undefined implementation *
271  ****************************/
272 #else
273 gpointer expose_setup(GtkWidget *widget) { return NULL; }
274 gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
275 {
276         g_message("unimplemented");
277         return FALSE;
278 }
279 #endif
280
281
282
283 /***************
284  * Common code *
285  ***************/
286 gboolean key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
287 {
288         if (event->keyval == GDK_q)
289                 gtk_main_quit();
290         return FALSE;
291 }
292 int main(int argc, char **argv)
293 {
294         gtk_init_check(&argc, &argv);
295         GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
296         GtkWidget *box    = gtk_vbox_new(FALSE, 5);
297         GtkWidget *draw   = gtk_drawing_area_new();
298         GtkWidget *button = gtk_button_new_with_label("Hello, World");
299         gpointer   data   = expose_setup(draw);
300         g_signal_connect(window, "destroy",         G_CALLBACK(gtk_main_quit),    NULL);
301         g_signal_connect(window, "key-press-event", G_CALLBACK(key_press_event),  NULL);
302         g_signal_connect(draw,   "expose-event",    G_CALLBACK(expose_event),     data);
303         gtk_widget_set_size_request(draw,   300, 300);
304         gtk_widget_set_size_request(button, -1,  50);
305         gtk_box_pack_start(GTK_BOX(box), draw,   TRUE,  TRUE, 0);
306         gtk_box_pack_start(GTK_BOX(box), button, FALSE, TRUE, 0);
307         gtk_container_add(GTK_CONTAINER(window), box);
308         gtk_widget_show_all(window);
309         gtk_main();
310         return 0;
311 }