From c1d21f2a47e34362ee1d939bca8ca082f5474b33 Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Fri, 4 Jan 2013 15:23:14 +0000 Subject: Import initial git-svn-id: file:///var/svn/2013-gpudataviz/trunk@2 371a6b4a-a258-45f8-9dcc-bdd82ce0ac9d --- src/boring_parts.cc | 101 +++++++++++++ src/boring_parts.h | 8 ++ src/compil.sh | 43 ++++++ src/gpudataviz.cc | 169 ++++++++++++++++++++++ src/gpudataviz.h | 0 src/gtk_includes.h | 16 +++ src/gtk_win_main.cc | 28 ++++ src/gtk_win_main.h | 21 +++ src/my_GTK_GL_scene.h | 23 +++ tests/compil.sh | 1 + tests/gtk_gl.cc | 388 ++++++++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 798 insertions(+) create mode 100644 src/boring_parts.cc create mode 100644 src/boring_parts.h create mode 100755 src/compil.sh create mode 100644 src/gpudataviz.cc create mode 100644 src/gpudataviz.h create mode 100644 src/gtk_includes.h create mode 100644 src/gtk_win_main.cc create mode 100644 src/gtk_win_main.h create mode 100644 src/my_GTK_GL_scene.h create mode 100755 tests/compil.sh create mode 100644 tests/gtk_gl.cc diff --git a/src/boring_parts.cc b/src/boring_parts.cc new file mode 100644 index 0000000..3affae9 --- /dev/null +++ b/src/boring_parts.cc @@ -0,0 +1,101 @@ +#include "boring_parts.h" + +#define RETURN_IF_FAIL(expr) do { \ + int res=(expr); \ + if ( res != 0 ) return res; \ +} while(0) + +// TODO : print streamsdk::getOpenCLErrorCodeStr(res) +#define CL_RETURN_VAL_IF_FAIL(val, expr) do { \ + cl_int res=(expr); \ + if ( res != CL_SUCCESS ) { \ + std::cerr << "file " << __FILE__ << ": line " << __LINE__ << " (" << __PRETTY_FUNCTION__ \ + << "): '" << "expr" << "' failed (return code : " << res << ")" << std::endl; \ + return val; \ + } \ +} while(0) + +int initLibs() { + + // FIXME : unused + RETURN_IF_FAIL( initOpenCL() ); + + return 0; +} + +int initOpenCL() { + cl_uint id, numPlatforms, numDevices; + char pbuf[100]; + std::string dTypeStr; + cl_platform_id *platforms, platform; + cl_device_id *devices, device; + + // Get platform count + CL_RETURN_VAL_IF_FAIL(1, + clGetPlatformIDs(0, NULL, &numPlatforms) + ); + + std::cout << "Detected " << numPlatforms << " platform(s)" << std::endl; + if ( ! ( numPlatforms > 0 ) ) return 2; + + // Allocate room for all platform IDs + platforms = new cl_platform_id[numPlatforms]; + + // Get platform IDs + CL_RETURN_VAL_IF_FAIL(3, + clGetPlatformIDs(numPlatforms, platforms, &numPlatforms) + ); + + // Enumerate platforms and grab informations + for(id=0;id 0 ) ) return 12; + + // Allocate room for all devices IDs + devices = new cl_device_id[numDevices]; + + // Get devices IDs + CL_RETURN_VAL_IF_FAIL(13, + clGetDeviceIDs(platform,CL_DEVICE_TYPE_ALL,numDevices,devices,&numDevices) + ); + + // Enumerate devices and grab informations + for(id=0;id +#include +#include "gtk_includes.h" + +int initLibs(); +int initOpenCL(); +int initGTK(); + diff --git a/src/compil.sh b/src/compil.sh new file mode 100755 index 0000000..4afcc2e --- /dev/null +++ b/src/compil.sh @@ -0,0 +1,43 @@ +#!/bin/bash -e + +clear + +set -x +CXX="g++ -Wall -g" +BUILD_PATH="../build" + +AMDAPP_PATH="/opt/AMDAPP" + +INCLUDES="" +LIBS="" + +# OpenCL +INCLUDES="$INCLUDES -I $AMDAPP_PATH/include" +LIBS="$LIBS -lOpenCL" + +# GTKGLEXT +INCLUDES="$INCLUDES $(pkg-config --cflags gtkglextmm-1.2)" +LIBS="$LIBS $(pkg-config --libs gtkglextmm-1.2)" + +set +x + +function build_cxx() { + echo "$PS4$CXX \$INCLUDES -o $BUILD_PATH/$1 -c $2" + $CXX $INCLUDES -o $BUILD_PATH/$1 -c $2 +} + +function link_cxx() { + out=$1 + shift 1 + echo "$PS4$CXX -o $BUILD_PATH/$out $* \$LIBS" + $CXX $* -o $BUILD_PATH/$out $LIBS +} + +rm $BUILD_PATH/* || true + +build_cxx gpudataviz.o gpudataviz.cc +build_cxx boring_parts.o boring_parts.cc +build_cxx gtk_win_main.o gtk_win_main.cc + +link_cxx gpudataviz $BUILD_PATH/*.o + diff --git a/src/gpudataviz.cc b/src/gpudataviz.cc new file mode 100644 index 0000000..bcd498e --- /dev/null +++ b/src/gpudataviz.cc @@ -0,0 +1,169 @@ +#include + +#include "gpudataviz.h" +#include "boring_parts.h" +#include "gtk_win_main.h" +#include "my_GTK_GL_scene.h" + +// Macro to make things readable in main() function +#define EXIT_IF_FAIL(val, expr) do { \ + if ( ! (expr) ) { \ + std::cerr << "Init error " << val << std::endl; \ + exit(val); \ + } \ +} while(0) + +#define CALL_TRACE do { \ + std::cout << "trace " <<__PRETTY_FUNCTION__ << std::endl; \ +} while(0) + +int main(int argc, char* argv[]) { + CALL_TRACE; + + int meshWidth=64, meshHeight=64; // TODO : those vars should not be hardcoded + + // Initialize GTK + Gtk::Main gtkKit(argc, argv); // gtk itself + Gtk::GL::init(argc, argv); // gtkglextmm + + // Query and print OpenGL version + int glVersionMajor, glVersionMinor; + EXIT_IF_FAIL(1, Gdk::GL::query_version(glVersionMajor, glVersionMinor) ); + std::cout << "OpenGL extension version - " << glVersionMajor << "." << glVersionMinor << std::endl; + + // Initialize OpenGL + Gdk::GL::ConfigMode glMode = Gdk::GL::MODE_RGB | Gdk::GL::MODE_DEPTH | Gdk::GL::MODE_DOUBLE; + Glib::RefPtr glconfig; + EXIT_IF_FAIL(2, glconfig=Gdk::GL::Config::create(glMode) ); + + // Initialize OpenCL + EXIT_IF_FAIL(3, initOpenCL()==0 ); // See boring_parts.cc + + // Initialize host work memory (array for all the vertex coordinates computed by OpenCL and displayed by OpenGL) + cl_float4 *hostWorkMem = (cl_float4 *) calloc(meshWidth * meshHeight, sizeof(cl_float4)); + EXIT_IF_FAIL(4, hostWorkMem); + + // Initialize the OpenGL scene + MyGTKGLScene glScene(glconfig); + + // Instantiate and run the GTK app + GTKWinMain gtkwinmain(glScene); + gtkKit.run(gtkwinmain); + + return 0; +} + +/* MyGTKGLScene implementation + I want to keep interesting code part in this file + in natural reading order +*/ +MyGTKGLScene::MyGTKGLScene(Glib::RefPtr &glconfig) { + CALL_TRACE; + set_gl_capability(glconfig); // Set OpenGL-capability to the widget. +} + +MyGTKGLScene::~MyGTKGLScene() { + CALL_TRACE; +} + +void MyGTKGLScene::on_size_request(Gtk::Requisition* requisition) { + CALL_TRACE; + + *requisition = Gtk::Requisition(); + requisition->width = 320; requisition->height = 240; +} + +void MyGTKGLScene::on_realize() { + CALL_TRACE; // This run once at window creation time + + Gtk::DrawingArea::on_realize(); + Glib::RefPtr glwindow = get_gl_window(); + + // *** OpenGL BEGIN *** + if (!glwindow->gl_begin(get_gl_context())) { + std::cerr << "Oups : glwindow->gl_begin(get_gl_context())" << std::endl; + return; + } + + GLUquadricObj* qobj = gluNewQuadric(); + gluQuadricDrawStyle(qobj, GLU_FILL); + glNewList(1, GL_COMPILE); + gluSphere(qobj, 1.0, 20, 20); + glEndList(); + + static GLfloat light_diffuse[] = {1.0, 0.0, 0.0, 1.0}; + static GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + glClearColor(1.0, 1.0, 1.0, 1.0); + glClearDepth(1.0); +/* + glViewport(0, 0, get_width(), get_height()); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(40.0, 1.0, 1.0, 10.0); + glMatrixMode(GL_MODELVIEW); +*/ + glLoadIdentity(); + gluLookAt(0.0, 0.0, 3.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + glTranslatef(0.0, 0.0, -3.0); + + glwindow->gl_end(); + // *** OpenGL END *** +} + +bool MyGTKGLScene::on_configure_event(GdkEventConfigure* event) { + CALL_TRACE ; // This run mainly when GTK GL Widget is resized + + Glib::RefPtr glwindow = get_gl_window(); + // *** OpenGL BEGIN *** + if (!glwindow->gl_begin(get_gl_context())) { + std::cerr << "Oups : glwindow->gl_begin(get_gl_context())" << std::endl; + return false; + } + int width = get_width(); + int height = get_height(); + GLdouble ratio = (GLdouble) width/height; + + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60.0, ratio, 0.1, 10.0); + glMatrixMode(GL_MODELVIEW); + + glwindow->gl_end(); + // *** OpenGL END *** + + return true; +} + +bool MyGTKGLScene::on_expose_event(GdkEventExpose* event) { + CALL_TRACE ; // This run mainly when GTK GL Widget have to be redrawn + + Glib::RefPtr glwindow = get_gl_window(); + + // *** OpenGL BEGIN *** + if (!glwindow->gl_begin(get_gl_context())) { + std::cerr << "Oups : glwindow->gl_begin(get_gl_context())" << std::endl; + return false; + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glCallList(1); + + glwindow->gl_end(); + // *** OpenGL END *** + + // Display the rendered image + glwindow->swap_buffers(); + + return true; +} + diff --git a/src/gpudataviz.h b/src/gpudataviz.h new file mode 100644 index 0000000..e69de29 diff --git a/src/gtk_includes.h b/src/gtk_includes.h new file mode 100644 index 0000000..4a6632f --- /dev/null +++ b/src/gtk_includes.h @@ -0,0 +1,16 @@ +#ifndef GTK_INCLUDES_H +#define GTK_INCLUDES_H + +#include +#include + +#ifdef G_OS_WIN32 +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#include +#include + +#endif /* GTK_INCLUDES_H */ + diff --git a/src/gtk_win_main.cc b/src/gtk_win_main.cc new file mode 100644 index 0000000..eca9df0 --- /dev/null +++ b/src/gtk_win_main.cc @@ -0,0 +1,28 @@ +#include "gtk_win_main.h" + + +GTKWinMain::GTKWinMain(MyGTKGLScene &glScene) + : m_VBox(false, 0), m_ButtonQuit("Quit"), m_GLScene(glScene) +{ + set_title(WIN_MAIN_TITLE); + set_reallocate_redraws(true); // Get automatically redrawn if any of their children changed allocation. + + // Add components to the window + add(m_VBox); + m_VBox.pack_start(m_GLScene); + m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0); + + // Link signal handlers on events + m_ButtonQuit.signal_clicked().connect( sigc::mem_fun(*this, >KWinMain::on_button_quit_clicked) ); + + show_all(); +} + +GTKWinMain::~GTKWinMain() +{} + +void GTKWinMain::on_button_quit_clicked() +{ + Gtk::Main::quit(); +} + diff --git a/src/gtk_win_main.h b/src/gtk_win_main.h new file mode 100644 index 0000000..d5338ed --- /dev/null +++ b/src/gtk_win_main.h @@ -0,0 +1,21 @@ +#include "gtk_includes.h" +#include "my_GTK_GL_scene.h" + +#define WIN_MAIN_TITLE "GPU Data Viz v0.1" + +class GTKWinMain : public Gtk::Window +{ + public: + GTKWinMain(MyGTKGLScene &glScene); + virtual ~GTKWinMain(); + + protected: + // signal handlers + void on_button_quit_clicked(); + + protected: + // member widgets + Gtk::VBox m_VBox; + Gtk::Button m_ButtonQuit; + MyGTKGLScene & m_GLScene; +}; diff --git a/src/my_GTK_GL_scene.h b/src/my_GTK_GL_scene.h new file mode 100644 index 0000000..dc8afbe --- /dev/null +++ b/src/my_GTK_GL_scene.h @@ -0,0 +1,23 @@ +#ifndef MY_GTK_GL_SCENE_H +#define MY_GTK_GL_SCENE_H + +#include "gtk_includes.h" + +// Class that will contain all the OpenGL logic for displaying the OpenCL computed data +// Implementation is kept in gpudataviz.cc (I want to keep interesting code part in this file) + +// TODO : rename it to MyGTKGLSceneWidget +class MyGTKGLScene : public Gtk::DrawingArea, public Gtk::GL::Widget +{ + public: + MyGTKGLScene(Glib::RefPtr &glconfig); + virtual ~MyGTKGLScene(); + + protected: + virtual void on_size_request(Gtk::Requisition* requisition); + virtual void on_realize(); + virtual bool on_configure_event(GdkEventConfigure* event); + virtual bool on_expose_event(GdkEventExpose* event); +}; + +#endif /*MY_GTK_GL_SCENE_H*/ diff --git a/tests/compil.sh b/tests/compil.sh new file mode 100755 index 0000000..ea18ccc --- /dev/null +++ b/tests/compil.sh @@ -0,0 +1 @@ +g++ $(pkg-config --cflags gtkglextmm-1.2) gtk_gl.cc $(pkg-config --libs gtkglextmm-1.2) diff --git a/tests/gtk_gl.cc b/tests/gtk_gl.cc new file mode 100644 index 0000000..0423612 --- /dev/null +++ b/tests/gtk_gl.cc @@ -0,0 +1,388 @@ +// -*- C++ -*- +/* + * simple.cc: + * Simple gtkglextmm example. + * + * written by Naofumi Yasufuku + */ + +#include +#include + +#include + +#include + +#ifdef G_OS_WIN32 +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#include +#include + + +// +// OpenGL frame buffer configuration utilities. +// + +struct GLConfigUtil +{ + static void print_gl_attrib(const Glib::RefPtr& glconfig, + const char* attrib_str, + int attrib, + bool is_boolean); + + static void examine_gl_attrib(const Glib::RefPtr& glconfig); +}; + +// +// Print a configuration attribute. +// +void GLConfigUtil::print_gl_attrib(const Glib::RefPtr& glconfig, + const char* attrib_str, + int attrib, + bool is_boolean) +{ + int value; + + if (glconfig->get_attrib(attrib, value)) + { + std::cout << attrib_str << " = "; + if (is_boolean) + std::cout << (value == true ? "true" : "false") << std::endl; + else + std::cout << value << std::endl; + } + else + { + std::cout << "*** Cannot get " + << attrib_str + << " attribute value\n"; + } +} + +// +// Print configuration attributes. +// +void GLConfigUtil::examine_gl_attrib(const Glib::RefPtr& glconfig) +{ + std::cout << "\nOpenGL visual configurations :\n\n"; + + std::cout << "glconfig->is_rgba() = " + << (glconfig->is_rgba() ? "true" : "false") + << std::endl; + std::cout << "glconfig->is_double_buffered() = " + << (glconfig->is_double_buffered() ? "true" : "false") + << std::endl; + std::cout << "glconfig->is_stereo() = " + << (glconfig->is_stereo() ? "true" : "false") + << std::endl; + std::cout << "glconfig->has_alpha() = " + << (glconfig->has_alpha() ? "true" : "false") + << std::endl; + std::cout << "glconfig->has_depth_buffer() = " + << (glconfig->has_depth_buffer() ? "true" : "false") + << std::endl; + std::cout << "glconfig->has_stencil_buffer() = " + << (glconfig->has_stencil_buffer() ? "true" : "false") + << std::endl; + std::cout << "glconfig->has_accum_buffer() = " + << (glconfig->has_accum_buffer() ? "true" : "false") + << std::endl; + + std::cout << std::endl; + + print_gl_attrib(glconfig, "Gdk::GL::USE_GL", Gdk::GL::USE_GL, true); + print_gl_attrib(glconfig, "Gdk::GL::BUFFER_SIZE", Gdk::GL::BUFFER_SIZE, false); + print_gl_attrib(glconfig, "Gdk::GL::LEVEL", Gdk::GL::LEVEL, false); + print_gl_attrib(glconfig, "Gdk::GL::RGBA", Gdk::GL::RGBA, true); + print_gl_attrib(glconfig, "Gdk::GL::DOUBLEBUFFER", Gdk::GL::DOUBLEBUFFER, true); + print_gl_attrib(glconfig, "Gdk::GL::STEREO", Gdk::GL::STEREO, true); + print_gl_attrib(glconfig, "Gdk::GL::AUX_BUFFERS", Gdk::GL::AUX_BUFFERS, false); + print_gl_attrib(glconfig, "Gdk::GL::RED_SIZE", Gdk::GL::RED_SIZE, false); + print_gl_attrib(glconfig, "Gdk::GL::GREEN_SIZE", Gdk::GL::GREEN_SIZE, false); + print_gl_attrib(glconfig, "Gdk::GL::BLUE_SIZE", Gdk::GL::BLUE_SIZE, false); + print_gl_attrib(glconfig, "Gdk::GL::ALPHA_SIZE", Gdk::GL::ALPHA_SIZE, false); + print_gl_attrib(glconfig, "Gdk::GL::DEPTH_SIZE", Gdk::GL::DEPTH_SIZE, false); + print_gl_attrib(glconfig, "Gdk::GL::STENCIL_SIZE", Gdk::GL::STENCIL_SIZE, false); + print_gl_attrib(glconfig, "Gdk::GL::ACCUM_RED_SIZE", Gdk::GL::ACCUM_RED_SIZE, false); + print_gl_attrib(glconfig, "Gdk::GL::ACCUM_GREEN_SIZE", Gdk::GL::ACCUM_GREEN_SIZE, false); + print_gl_attrib(glconfig, "Gdk::GL::ACCUM_BLUE_SIZE", Gdk::GL::ACCUM_BLUE_SIZE, false); + print_gl_attrib(glconfig, "Gdk::GL::ACCUM_ALPHA_SIZE", Gdk::GL::ACCUM_ALPHA_SIZE, false); + + std::cout << std::endl; +} + + +// +// Simple OpenGL scene. +// + +class SimpleGLScene : public Gtk::DrawingArea, + public Gtk::GL::Widget +{ + public: + SimpleGLScene(); + virtual ~SimpleGLScene(); + + protected: + virtual void on_realize(); + virtual bool on_configure_event(GdkEventConfigure* event); + virtual bool on_expose_event(GdkEventExpose* event); + +}; + +SimpleGLScene::SimpleGLScene() +{ + // + // Configure OpenGL-capable visual. + // + + Glib::RefPtr glconfig; + + // Try double-buffered visual + glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | + Gdk::GL::MODE_DEPTH | + Gdk::GL::MODE_DOUBLE); + if (!glconfig) + { + std::cerr << "*** Cannot find the double-buffered visual.\n" + << "*** Trying single-buffered visual.\n"; + + // Try single-buffered visual + glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | + Gdk::GL::MODE_DEPTH); + if (!glconfig) + { + std::cerr << "*** Cannot find any OpenGL-capable visual.\n"; + std::exit(1); + } + } + + // print frame buffer attributes. + GLConfigUtil::examine_gl_attrib(glconfig); + + // + // Set OpenGL-capability to the widget. + // + + set_gl_capability(glconfig); +} + +SimpleGLScene::~SimpleGLScene() +{ +} + +void SimpleGLScene::on_realize() +{ + // We need to call the base on_realize() + Gtk::DrawingArea::on_realize(); + + // + // Get GL::Window. + // + + Glib::RefPtr glwindow = get_gl_window(); + + // + // GL calls. + // + + // *** OpenGL BEGIN *** + if (!glwindow->gl_begin(get_gl_context())) + return; + + GLUquadricObj* qobj = gluNewQuadric(); + gluQuadricDrawStyle(qobj, GLU_FILL); + glNewList(1, GL_COMPILE); + gluSphere(qobj, 1.0, 20, 20); + glEndList(); + + static GLfloat light_diffuse[] = {1.0, 0.0, 0.0, 1.0}; + static GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + glClearColor(1.0, 1.0, 1.0, 1.0); + glClearDepth(1.0); + + glViewport(0, 0, get_width(), get_height()); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(40.0, 1.0, 1.0, 10.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.0, 0.0, 3.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + glTranslatef(0.0, 0.0, -3.0); + + glwindow->gl_end(); + // *** OpenGL END *** +} + +bool SimpleGLScene::on_configure_event(GdkEventConfigure* event) +{ + // + // Get GL::Window. + // + + Glib::RefPtr glwindow = get_gl_window(); + + // + // GL calls. + // + + // *** OpenGL BEGIN *** + if (!glwindow->gl_begin(get_gl_context())) + return false; + + glViewport(0, 0, get_width(), get_height()); + + glwindow->gl_end(); + // *** OpenGL END *** + + return true; +} + +bool SimpleGLScene::on_expose_event(GdkEventExpose* event) +{ + // + // Get GL::Window. + // + + Glib::RefPtr glwindow = get_gl_window(); + + // + // GL calls. + // + + // *** OpenGL BEGIN *** + if (!glwindow->gl_begin(get_gl_context())) + return false; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glCallList(1); + + // Swap buffers. + if (glwindow->is_double_buffered()) + glwindow->swap_buffers(); + else + glFlush(); + + glwindow->gl_end(); + // *** OpenGL END *** + + return true; +} + + +// +// The application class. +// + +class Simple : public Gtk::Window +{ + public: + Simple(); + virtual ~Simple(); + + protected: + // signal handlers: + void on_button_quit_clicked(); + + protected: + // member widgets: + Gtk::VBox m_VBox; + SimpleGLScene m_SimpleGLScene; + Gtk::Button m_ButtonQuit; +}; + +Simple::Simple() + : m_VBox(false, 0), m_ButtonQuit("Quit") +{ + // + // Top-level window. + // + + set_title("Simple"); + + // Get automatically redrawn if any of their children changed allocation. + set_reallocate_redraws(true); + + add(m_VBox); + + // + // Simple OpenGL scene. + // + + m_SimpleGLScene.set_size_request(200, 200); + + m_VBox.pack_start(m_SimpleGLScene); + + // + // Simple quit button. + // + + m_ButtonQuit.signal_clicked().connect( + sigc::mem_fun(*this, &Simple::on_button_quit_clicked)); + + m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0); + + // + // Show window. + // + + show_all(); +} + +Simple::~Simple() +{} + +void Simple::on_button_quit_clicked() +{ + Gtk::Main::quit(); +} + + +// +// Main. +// + +int main(int argc, char** argv) +{ + Gtk::Main kit(argc, argv); + + // + // Init gtkglextmm. + // + + Gtk::GL::init(argc, argv); + + // + // Query OpenGL extension version. + // + + int major, minor; + Gdk::GL::query_version(major, minor); + std::cout << "OpenGL extension version - " + << major << "." << minor << std::endl; + + // + // Instantiate and run the application. + // + + Simple simple; + + kit.run(simple); + + return 0; +} + -- cgit v1.2.3