summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2013-01-04 15:23:14 +0000
committerLudovic Pouzenc <ludovic@pouzenc.fr>2013-01-04 15:23:14 +0000
commitc1d21f2a47e34362ee1d939bca8ca082f5474b33 (patch)
tree46d7a62a4182bcbc4b490b42b181df81877f08be
parent854df3320b1ea19e8c145c43e0a7d038843e990c (diff)
download2013-gpudataviz-c1d21f2a47e34362ee1d939bca8ca082f5474b33.tar.gz
2013-gpudataviz-c1d21f2a47e34362ee1d939bca8ca082f5474b33.tar.bz2
2013-gpudataviz-c1d21f2a47e34362ee1d939bca8ca082f5474b33.zip
Import initial
git-svn-id: file:///var/svn/2013-gpudataviz/trunk@2 371a6b4a-a258-45f8-9dcc-bdd82ce0ac9d
-rw-r--r--src/boring_parts.cc101
-rw-r--r--src/boring_parts.h8
-rwxr-xr-xsrc/compil.sh43
-rw-r--r--src/gpudataviz.cc169
-rw-r--r--src/gpudataviz.h0
-rw-r--r--src/gtk_includes.h16
-rw-r--r--src/gtk_win_main.cc28
-rw-r--r--src/gtk_win_main.h21
-rw-r--r--src/my_GTK_GL_scene.h23
-rwxr-xr-xtests/compil.sh1
-rw-r--r--tests/gtk_gl.cc388
11 files changed, 798 insertions, 0 deletions
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<numPlatforms;id++) {
+ CL_RETURN_VAL_IF_FAIL(4,
+ clGetPlatformInfo(platforms[id], CL_PLATFORM_VENDOR, sizeof(pbuf), pbuf, NULL)
+ );
+ std::cout << "Platform " << id << " : " << pbuf << std::endl;
+ }
+
+ // Take the first one FIXME : do more !
+ platform = platforms[0];
+
+ // Get device count
+ CL_RETURN_VAL_IF_FAIL(11,
+ clGetDeviceIDs(platform,CL_DEVICE_TYPE_ALL,0,NULL,&numDevices)
+ );
+
+ std::cout << "\tDetected " << numDevices << " device(s) for platform " << platform << std::endl;
+ if ( ! ( numDevices > 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<numDevices;id++) {
+ cl_device_type dType;
+
+ CL_RETURN_VAL_IF_FAIL(14,
+ clGetDeviceInfo(devices[id], CL_DEVICE_TYPE, sizeof(dType), &dType, NULL)
+ );
+
+ switch(dType) {
+ case CL_DEVICE_TYPE_GPU: dTypeStr="gpu"; break;
+ case CL_DEVICE_TYPE_CPU: dTypeStr="cpu"; break;
+ default: dTypeStr="(not supported)"; break;
+ }
+ std::cout << "\tDevice " << id << " type is " << dTypeStr << std::endl;
+ }
+
+ // Take the first one FIXME : do more !
+ device=devices[0];
+ std::cout << "\tWill using device 0 (" << device << ")" << std::endl;
+
+ delete [] devices;
+ delete [] platforms;
+
+ return 0;
+}
+
diff --git a/src/boring_parts.h b/src/boring_parts.h
new file mode 100644
index 0000000..fc4e09b
--- /dev/null
+++ b/src/boring_parts.h
@@ -0,0 +1,8 @@
+#include <iostream>
+#include <CL/opencl.h>
+#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 <iostream>
+
+#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<Gdk::GL::Config> 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<Gdk::GL::Config> &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<Gdk::GL::Window> 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<Gdk::GL::Window> 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<Gdk::GL::Window> 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
--- /dev/null
+++ b/src/gpudataviz.h
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 <gtkmm.h>
+#include <gtkglmm.h>
+
+#ifdef G_OS_WIN32
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#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, &GTKWinMain::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<MyGTKGLScene>
+{
+ public:
+ MyGTKGLScene(Glib::RefPtr<Gdk::GL::Config> &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 <naofumi@users.sourceforge.net>
+ */
+
+#include <iostream>
+#include <cstdlib>
+
+#include <gtkmm.h>
+
+#include <gtkglmm.h>
+
+#ifdef G_OS_WIN32
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+
+//
+// OpenGL frame buffer configuration utilities.
+//
+
+struct GLConfigUtil
+{
+ static void print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig,
+ const char* attrib_str,
+ int attrib,
+ bool is_boolean);
+
+ static void examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig);
+};
+
+//
+// Print a configuration attribute.
+//
+void GLConfigUtil::print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& 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<const Gdk::GL::Config>& 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<SimpleGLScene>
+{
+ 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<Gdk::GL::Config> 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<Gdk::GL::Window> 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<Gdk::GL::Window> 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<Gdk::GL::Window> 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;
+}
+