]> Pileus Git - grits/commitdiff
Add GL bindings example program
authorAndy Spencer <andy753421@gmail.com>
Sat, 18 Jun 2011 22:16:27 +0000 (22:16 +0000)
committerAndy Spencer <andy753421@gmail.com>
Sat, 18 Jun 2011 22:16:27 +0000 (22:16 +0000)
Basic standalone program that draws a circle using:
  - Cairo
  - GktGLExt
  - GLX (X11)
  - WGL (Win32)
  - CGL (Mac OS, not implemented)

examples/gl/gl.c [new file with mode: 0644]
examples/gl/mkfile [new file with mode: 0644]

diff --git a/examples/gl/gl.c b/examples/gl/gl.c
new file mode 100644 (file)
index 0000000..39fd1e0
--- /dev/null
@@ -0,0 +1,311 @@
+#include <math.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+//#define USE_CAIRO
+#define USE_GTKGLEXT
+//#define USE_GLX
+//#define USE_WGL
+//#define USE_CGL
+
+/************************
+ * Cairo implementation *
+ ************************/
+#if defined(USE_CAIRO)
+#include <gdk/gdkwin32.h>
+gpointer expose_setup(GtkWidget *widget) { return NULL; }
+gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
+{
+       GtkAllocation alloc;
+       gtk_widget_get_allocation(widget, &alloc);
+       cairo_t *cairo = gdk_cairo_create(gtk_widget_get_window(widget));
+       cairo_set_source_rgb(cairo, 1, 1, 1);
+       cairo_arc(cairo,
+               alloc.x + alloc.width/2,
+               alloc.y + alloc.height/2,
+               MIN(alloc.width/2,alloc.height/2),
+               0, 2*G_PI);
+       cairo_fill(cairo);
+       return FALSE;
+}
+
+
+/***************************
+ * GtkGlExt implementation *
+ ***************************/
+#elif defined(USE_GTKGLEXT)
+#include <gtk/gtkgl.h>
+#include <GL/gl.h>
+#include <gdk/gdkwin32.h>
+void realize(GtkWidget *widget, gpointer user_data)
+{
+       gdk_window_ensure_native(gtk_widget_get_window(widget));
+}
+gpointer expose_setup(GtkWidget *widget)
+{
+       //GdkGLConfig *glconfig = gdk_gl_config_new_by_mode(
+       //              GDK_GL_MODE_RGBA   | GDK_GL_MODE_DEPTH |
+       //              GDK_GL_MODE_ALPHA);
+       GdkGLConfig *glconfig = gdk_gl_config_new_by_mode(
+                       GDK_GL_MODE_RGBA   | GDK_GL_MODE_DEPTH |
+                       GDK_GL_MODE_ALPHA  | GDK_GL_MODE_DOUBLE);
+       gtk_widget_set_gl_capability(widget,
+                       glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
+       return NULL;
+}
+gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
+{
+       GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
+       g_message("window: w=%x tl=%x",
+               (guint)GDK_WINDOW_HWND(gtk_widget_get_window(widget)),
+               (guint)GDK_WINDOW_HWND(gtk_widget_get_window(toplevel)));
+
+       GtkAllocation alloc;
+       gtk_widget_get_allocation(widget, &alloc);
+       GdkGLContext  *glcontext  = gtk_widget_get_gl_context(widget);
+       GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget);
+       gdk_gl_drawable_gl_begin(gldrawable, glcontext);
+       glViewport(0, 0, alloc.width, alloc.height);
+       glClear(GL_COLOR_BUFFER_BIT);
+       glColor3f(1.0, 1.0, 1.0);
+       glBegin(GL_TRIANGLE_FAN);
+       glVertex2f(0.0, 0.0);
+       for (double i = 0; i < 2*G_PI; i+=(2*G_PI)/100)
+               glVertex2d(sin(i), cos(i));
+       glEnd();
+       gdk_gl_drawable_swap_buffers(gldrawable);
+       gdk_gl_drawable_gl_end(gldrawable);
+       return FALSE;
+}
+
+
+/**********************
+ * X11 implementation *
+ **********************/
+#elif defined(USE_GLX)
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <gdk/gdkx.h>
+void realize(GtkWidget *widget, gpointer user_data)
+{
+      gdk_window_ensure_native(gtk_widget_get_window(widget));
+}
+gpointer expose_setup(GtkWidget *widget)
+{
+       GdkScreen *screen    = gdk_screen_get_default();
+       Display   *xdisplay  = GDK_SCREEN_XDISPLAY(screen);
+       gint       nscreen   = GDK_SCREEN_XNUMBER(screen);
+
+       /* Create context */
+       int attribs[]        = {GLX_RGBA,
+                               GLX_RED_SIZE,    1,
+                               GLX_GREEN_SIZE,  1,
+                               GLX_BLUE_SIZE,   1,
+                               GLX_ALPHA_SIZE,  1,
+                               GLX_DOUBLEBUFFER,
+                               GLX_DEPTH_SIZE,  1,
+                               None};
+       XVisualInfo *xvinfo  = glXChooseVisual(xdisplay, nscreen, attribs);
+       GLXContext   context = glXCreateContext(xdisplay, xvinfo, 0, False);
+
+       /* Fix up colormap */
+       GdkVisual   *visual  = gdk_x11_screen_lookup_visual(screen, xvinfo->visualid);
+       GdkColormap *cmap    = gdk_colormap_new(visual, FALSE);
+       gtk_widget_set_colormap(widget, cmap);
+
+       /* Disable GTK double buffering */
+       gtk_widget_set_double_buffered(widget, FALSE);
+
+       return context;
+}
+gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, GLXContext context)
+{
+       /* Make current */
+       Display     *xdisplay = GDK_SCREEN_XDISPLAY(gdk_screen_get_default());
+       Window       xwindow  = GDK_WINDOW_XID(gtk_widget_get_window(widget));
+       glXMakeCurrent(xdisplay, xwindow, context);
+
+       GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
+       g_message("window: w=%x tl=%x",
+               (guint)GDK_WINDOW_XID(gtk_widget_get_window(widget)),
+               (guint)GDK_WINDOW_XID(gtk_widget_get_window(toplevel)));
+
+       /* Drawing */
+       GtkAllocation alloc;
+       gtk_widget_get_allocation(widget, &alloc);
+       glViewport(0, 0, alloc.width, alloc.height);
+       glClear(GL_COLOR_BUFFER_BIT);
+       glColor3f(1.0, 1.0, 1.0);
+       glBegin(GL_TRIANGLE_FAN);
+       glVertex2f(0.0, 0.0);
+       for (double i = 0; i < 2*G_PI; i+=(2*G_PI)/100)
+               glVertex2d(sin(i), cos(i));
+       glEnd();
+
+       /* Swap buffers */
+       glXSwapBuffers(xdisplay, xwindow);
+       return FALSE;
+}
+
+
+/************************
+ * Win32 implementation *
+ ************************/
+#elif defined(USE_WGL)
+#include <GL/gl.h>
+#include <windows.h>
+#include <gdk/gdkwin32.h>
+void realize(GtkWidget *widget, gpointer user_data)
+{
+       gdk_window_ensure_native(gtk_widget_get_window(widget));
+}
+gpointer expose_setup(GtkWidget *widget)
+{
+       /* Create context */
+       //HWND  hwnd = GDK_WINDOW_HWND(gtk_widget_get_window(widget));
+       //HGLRC hDC  = GetDC(hwnd);           // get the device context for window
+       //HDC   hRC  = wglCreateContext(hDC); // create rendering context
+       //wglMakeCurrent(hDC,hRC);            // make rendering context current
+
+       /* Delete context */
+       //wglMakeCurrent(hDC,NULL);    // deselect rendering context
+       //wglDeleteContext(hRC);       // delete rendering context
+       //PostQuitMessage(0);          // send wm_quit
+
+       /* Disable GTK double buffering */
+       gtk_widget_set_double_buffered(widget, FALSE);
+       return FALSE;
+}
+gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
+{
+       GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
+       GdkWindow *window   = gtk_widget_get_window(widget);
+       GdkWindow *topwin   = gtk_widget_get_window(toplevel);
+       gdk_window_ensure_native(window);
+
+       PIXELFORMATDESCRIPTOR pfo = {}, pfd = {
+               .nSize       = sizeof(pfd),
+               .nVersion    = 1,
+               .dwFlags     = PFD_DRAW_TO_WINDOW // "Correct" way
+                            | PFD_SUPPORT_OPENGL
+                            | PFD_DOUBLEBUFFER,
+               //.dwFlags     = PFD_SUPPORT_OPENGL  // Works in wine
+               //             | PFD_DRAW_TO_WINDOW,
+               .iPixelType  = PFD_TYPE_RGBA,
+               .cColorBits  = 24,
+               .cAlphaBits  = 8,
+               .cDepthBits  = 32,
+               .iLayerType  = PFD_MAIN_PLANE,
+       };
+       HWND  hwnd = GDK_WINDOW_HWND(window);
+       HDC   hDC  = GetDC(hwnd);           // get the device context for window
+       int   pf   = ChoosePixelFormat(hDC, &pfd);
+       int   st0  = DescribePixelFormat(hDC, pf, sizeof(pfd), &pfo);
+       int   st1  = SetPixelFormat(hDC, pf, &pfd);
+       HGLRC hRC  = wglCreateContext(hDC);
+       int   st2  = wglMakeCurrent(hDC, hRC);
+
+       g_message("dc: %p, %p, %p", hDC, GetDC(hwnd), wglGetCurrentDC());
+
+       g_message("window: pf=%d st=%d,%d,%d dc=%p rc=%p wins=%x=%x!=%x",
+               pf, st0,st1,st2, hDC, hRC, (guint)hwnd,
+               (guint)GDK_WINDOW_HWND(window),
+               (guint)GDK_WINDOW_HWND(topwin));
+
+       g_message("pdfOut: dwFlags=%lx=%lx, ipt=%x=%x, layer=%x=%x, {c,a,d}bits=%d,%d,%d",
+               pfo.dwFlags,    pfd.dwFlags,
+               pfo.iPixelType, pfd.iPixelType,
+               pfo.iLayerType, pfd.iLayerType,
+               pfo.cColorBits, pfo.cAlphaBits, pfo.cDepthBits);
+
+       /* Drawing */
+       GtkAllocation alloc = widget->allocation;
+       glViewport(0, 0, alloc.width, alloc.height);
+       g_message("alloc: %dx%d", alloc.width, alloc.height);
+       glClear(GL_COLOR_BUFFER_BIT);
+       glColor3f(1.0, 1.0, 1.0);
+       glBegin(GL_TRIANGLE_FAN);
+       glVertex2f(0.0, 0.0);
+       for (double i = 0; i < 2*G_PI; i+=(2*G_PI)/100)
+               glVertex2d(sin(i), cos(i));
+       glEnd();
+
+       /* Swap buffers */
+       SwapBuffers(hDC);
+
+       /* Cleanup */
+       wglMakeCurrent(NULL, NULL);
+       wglDeleteContext(hRC);
+       return TRUE;
+}
+
+
+/**************************
+ * Mac OSX implementation *
+ **************************/
+#elif defined(USE_CGL)
+#include <GL/gl.h>
+gpointer expose_setup(GtkWidget *widget)
+{
+       return FALSE;
+}
+gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
+{
+       /* Drawing */
+       GtkAllocation alloc;
+       gtk_widget_get_allocation(widget, &alloc);
+       glViewport(0, 0, alloc.width, alloc.height);
+       glClear(GL_COLOR_BUFFER_BIT);
+       glColor3f(1.0, 1.0, 1.0);
+       glBegin(GL_TRIANGLE_FAN);
+       glVertex2f(0.0, 0.0);
+       for (double i = 0; i < 2*G_PI; i+=(2*G_PI)/100)
+               glVertex2d(sin(i), cos(i));
+       glEnd();
+       return FALSE;
+}
+
+
+/****************************
+ * Undefined implementation *
+ ****************************/
+#else
+gpointer expose_setup(GtkWidget *widget) { return NULL; }
+gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
+{
+       g_message("unimplemented");
+       return FALSE;
+}
+#endif
+
+
+
+/***************
+ * Common code *
+ ***************/
+gboolean key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
+{
+       if (event->keyval == GDK_q)
+               gtk_main_quit();
+       return FALSE;
+}
+int main(int argc, char **argv)
+{
+       gtk_init_check(&argc, &argv);
+       GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       GtkWidget *box    = gtk_vbox_new(FALSE, 5);
+       GtkWidget *draw   = gtk_drawing_area_new();
+       GtkWidget *button = gtk_button_new_with_label("Hello, World");
+       gpointer   data   = expose_setup(draw);
+       g_signal_connect(window, "destroy",         G_CALLBACK(gtk_main_quit),    NULL);
+       g_signal_connect(window, "key-press-event", G_CALLBACK(key_press_event),  NULL);
+       g_signal_connect(draw,   "expose-event",    G_CALLBACK(expose_event),     data);
+       gtk_widget_set_size_request(draw,   300, 300);
+       gtk_widget_set_size_request(button, -1,  50);
+       gtk_box_pack_start(GTK_BOX(box), draw,   TRUE,  TRUE, 0);
+       gtk_box_pack_start(GTK_BOX(box), button, FALSE, TRUE, 0);
+       gtk_container_add(GTK_CONTAINER(window), box);
+       gtk_widget_show_all(window);
+       gtk_main();
+       return 0;
+}
diff --git a/examples/gl/mkfile b/examples/gl/mkfile
new file mode 100644 (file)
index 0000000..319416f
--- /dev/null
@@ -0,0 +1,11 @@
+PROGS=gl
+PKGS=gtk+-2.0 gtkglext-1.0
+LIBS=-lm
+
+#default:V: run
+
+ARCH=i686-pc-mingw32-
+EXT=.exe
+default:V: gl.exe
+       wine $prereq
+<$HOME/lib/mkcommon