added gtk-x11/gl_test.cpp
@@ -0,0 +1,114 @@ | ||
1 | +// gl_test.cpp: OpenGL test program for GTK+2/X11 | |
2 | + | |
3 | +// Copyright Takeshi Mouri 2008. | |
4 | +// Distributed under the Boost Software License, Version 1.0. | |
5 | +// (See accompanying file LICENSE_1_0.txt or copy at | |
6 | +// http://www.boost.org/LICENSE_1_0.txt) | |
7 | + | |
8 | +// See http://hamigaki.sourceforge.jp/ for library home page. | |
9 | + | |
10 | +#include <gdk/gdkx.h> | |
11 | +#include <gtk/gtk.h> | |
12 | +#include <GL/gl.h> | |
13 | +#include <GL/glx.h> | |
14 | + | |
15 | +class gl_window_data | |
16 | +{ | |
17 | +public: | |
18 | + explicit gl_window_data(::GtkWidget* widget) | |
19 | + : widget_(widget), gc_(0), ctx_(0) | |
20 | + { | |
21 | + } | |
22 | + | |
23 | + void create_gl_context() | |
24 | + { | |
25 | + gc_ = ::gdk_gc_new(widget_->window); | |
26 | + ::Display* dpy = ::gdk_x11_gc_get_xdisplay(gc_); | |
27 | + | |
28 | + ::Window window = GDK_WINDOW_XID(widget_->window); | |
29 | + | |
30 | + ::GdkScreen* scr = ::gdk_drawable_get_screen(widget_->window); | |
31 | + int scr_num = ::gdk_screen_get_number(scr); | |
32 | + | |
33 | + int attrs[] = { GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, 0 }; | |
34 | + ::XVisualInfo* vi = ::glXChooseVisual(dpy, scr_num, attrs); | |
35 | + | |
36 | + ctx_ = ::glXCreateContext(dpy, vi, 0, True); | |
37 | + ::glXMakeCurrent(dpy, window, ctx_); | |
38 | + | |
39 | + ::XFree(vi); | |
40 | + } | |
41 | + | |
42 | + void destroy_gl_context() | |
43 | + { | |
44 | + ::Display* dpy = ::gdk_x11_gc_get_xdisplay(gc_); | |
45 | + ::glXMakeCurrent(dpy, 0, 0); | |
46 | + ::glXDestroyContext(dpy, ctx_); | |
47 | + ::gdk_gc_unref(gc_); | |
48 | + } | |
49 | + | |
50 | + void swap_buffers() | |
51 | + { | |
52 | + ::Display* dpy = ::gdk_x11_gc_get_xdisplay(gc_); | |
53 | + ::Window window = GDK_WINDOW_XID(widget_->window); | |
54 | + ::glXSwapBuffers(dpy, window); | |
55 | + } | |
56 | + | |
57 | + void clear() | |
58 | + { | |
59 | + ::glClearColor(0.0, 0.0, 1.0, 0.0); | |
60 | + ::glClear(GL_COLOR_BUFFER_BIT); | |
61 | + } | |
62 | + | |
63 | +private: | |
64 | + ::GtkWidget* widget_; | |
65 | + ::GdkGC* gc_; | |
66 | + ::GLXContext ctx_; | |
67 | + | |
68 | + gl_window_data(const gl_window_data&); | |
69 | + gl_window_data& operator=(const gl_window_data&); | |
70 | +}; | |
71 | + | |
72 | +void destroy(::GtkWidget* widget, ::gpointer user_data) | |
73 | +{ | |
74 | + ::gtk_main_quit(); | |
75 | +} | |
76 | + | |
77 | +::gboolean | |
78 | +delete_event(::GtkWidget* widget, ::GdkEvent* event, ::gpointer user_data) | |
79 | +{ | |
80 | + gl_window_data& data = *static_cast<gl_window_data*>(user_data); | |
81 | + data.destroy_gl_context(); | |
82 | + return FALSE; | |
83 | +} | |
84 | + | |
85 | +::gboolean draw(::gpointer user_data) | |
86 | +{ | |
87 | + gl_window_data& data = *static_cast<gl_window_data*>(user_data); | |
88 | + data.clear(); | |
89 | + data.swap_buffers(); | |
90 | + return TRUE; | |
91 | +} | |
92 | + | |
93 | +int main(int argc, char* argv[]) | |
94 | +{ | |
95 | + ::gtk_init(&argc, &argv); | |
96 | + | |
97 | + ::GtkWidget* window = ::gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
98 | + | |
99 | + ::gtk_widget_show(window); | |
100 | + | |
101 | + gl_window_data data(window); | |
102 | + data.create_gl_context(); | |
103 | + | |
104 | + ::g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), 0); | |
105 | + | |
106 | + ::g_signal_connect( | |
107 | + G_OBJECT(window), "delete-event", G_CALLBACK(delete_event), &data); | |
108 | + | |
109 | + ::g_idle_add(&draw, &data); | |
110 | + | |
111 | + ::gtk_main(); | |
112 | + | |
113 | + return 0; | |
114 | +} |