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